hotspot/src/share/vm/adlc/output_c.cpp
changeset 7433 b418028612ad
parent 6418 6671edbd230e
child 8324 a9933c6c5a95
--- a/hotspot/src/share/vm/adlc/output_c.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/hotspot/src/share/vm/adlc/output_c.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1496,8 +1496,8 @@
   unsigned      i;
 
   // Generate Expand function header
-  fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list, Node* mem) {\n", node->_ident);
-  fprintf(fp,"Compile* C = Compile::current();\n");
+  fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident);
+  fprintf(fp, "  Compile* C = Compile::current();\n");
   // Generate expand code
   if( node->expands() ) {
     const char   *opid;
@@ -1818,6 +1818,12 @@
     }
   }
 
+  // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
+  // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
+  if (node->is_mach_constant()) {
+    fprintf(fp,"  add_req(C->mach_constant_base_node());\n");
+  }
+
   fprintf(fp,"\n");
   if( node->expands() ) {
     fprintf(fp,"  return result;\n");
@@ -1924,7 +1930,17 @@
         // No state needed.
         assert( _opclass == NULL,
                 "'primary', 'secondary' and 'tertiary' don't follow operand.");
-      } else {
+      }
+      else if ((strcmp(rep_var, "constanttablebase") == 0) ||
+               (strcmp(rep_var, "constantoffset")    == 0) ||
+               (strcmp(rep_var, "constantaddress")   == 0)) {
+        if (!_inst.is_mach_constant()) {
+          _AD.syntax_err(_encoding._linenum,
+                         "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
+                         rep_var, _encoding._name);
+        }
+      }
+      else {
         // Lookup its position in parameter list
         int   param_no  = _encoding.rep_var_index(rep_var);
         if ( param_no == -1 ) {
@@ -2380,6 +2396,15 @@
                         rep_var, _inst._ident, _encoding._name);
       }
     }
+    else if (strcmp(rep_var, "constanttablebase") == 0) {
+      fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))");
+    }
+    else if (strcmp(rep_var, "constantoffset") == 0) {
+      fprintf(_fp, "constant_offset()");
+    }
+    else if (strcmp(rep_var, "constantaddress") == 0) {
+      fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())");
+    }
     else {
       // Lookup its position in parameter list
       int   param_no  = _encoding.rep_var_index(rep_var);
@@ -2465,37 +2490,39 @@
   fprintf(fp,"}\n");
 }
 
-void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
-  InsEncode *ins_encode = inst._insencode;
+// defineEmit -----------------------------------------------------------------
+void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
+  InsEncode* encode = inst._insencode;
 
   // (1)
   // Output instruction's emit prototype
-  fprintf(fp,"void  %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n",
-          inst._ident);
+  fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident);
 
   // If user did not define an encode section,
   // provide stub that does not generate any machine code.
-  if( (_encode == NULL) || (ins_encode == NULL) ) {
+  if( (_encode == NULL) || (encode == NULL) ) {
     fprintf(fp, "  // User did not define an encode section.\n");
-    fprintf(fp,"}\n");
+    fprintf(fp, "}\n");
     return;
   }
 
   // Save current instruction's starting address (helps with relocation).
-  fprintf(fp, "    cbuf.set_insts_mark();\n");
-
-  // // // idx0 is only needed for syntactic purposes and only by "storeSSI"
-  // fprintf( fp, "    unsigned idx0  = 0;\n");
+  fprintf(fp, "  cbuf.set_insts_mark();\n");
+
+  // For MachConstantNodes which are ideal jump nodes, fill the jump table.
+  if (inst.is_mach_constant() && inst.is_ideal_jump()) {
+    fprintf(fp, "  ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
+  }
 
   // Output each operand's offset into the array of registers.
-  inst.index_temps( fp, _globalNames );
+  inst.index_temps(fp, _globalNames);
 
   // Output this instruction's encodings
   const char *ec_name;
   bool        user_defined = false;
-  ins_encode->reset();
-  while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) {
-    fprintf(fp, "  {");
+  encode->reset();
+  while ((ec_name = encode->encode_class_iter()) != NULL) {
+    fprintf(fp, "  {\n");
     // Output user-defined encoding
     user_defined           = true;
 
@@ -2507,25 +2534,25 @@
       abort();
     }
 
-    if (ins_encode->current_encoding_num_args() != encoding->num_args()) {
-      globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
-                           inst._ident, ins_encode->current_encoding_num_args(),
+    if (encode->current_encoding_num_args() != encoding->num_args()) {
+      globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+                           inst._ident, encode->current_encoding_num_args(),
                            ec_name, encoding->num_args());
     }
 
-    DefineEmitState  pending(fp, *this, *encoding, *ins_encode, inst );
+    DefineEmitState pending(fp, *this, *encoding, *encode, inst);
     encoding->_code.reset();
     encoding->_rep_vars.reset();
     // Process list of user-defined strings,
     // and occurrences of replacement variables.
     // Replacement Vars are pushed into a list and then output
-    while ( (ec_code = encoding->_code.iter()) != NULL ) {
-      if ( ! encoding->_code.is_signal( ec_code ) ) {
+    while ((ec_code = encoding->_code.iter()) != NULL) {
+      if (!encoding->_code.is_signal(ec_code)) {
         // Emit pending code
         pending.emit();
         pending.clear();
         // Emit this code section
-        fprintf(fp,"%s", ec_code);
+        fprintf(fp, "%s", ec_code);
       } else {
         // A replacement variable or one of its subfields
         // Obtain replacement variable from list
@@ -2536,7 +2563,7 @@
     // Emit pending code
     pending.emit();
     pending.clear();
-    fprintf(fp, "}\n");
+    fprintf(fp, "  }\n");
   } // end while instruction's encodings
 
   // Check if user stated which encoding to user
@@ -2545,7 +2572,86 @@
   }
 
   // (3) and (4)
-  fprintf(fp,"}\n");
+  fprintf(fp, "}\n");
+}
+
+// defineEvalConstant ---------------------------------------------------------
+void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
+  InsEncode* encode = inst._constant;
+
+  // (1)
+  // Output instruction's emit prototype
+  fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
+
+  // For ideal jump nodes, allocate a jump table.
+  if (inst.is_ideal_jump()) {
+    fprintf(fp, "  _constant = C->constant_table().allocate_jump_table(this);\n");
+  }
+
+  // If user did not define an encode section,
+  // provide stub that does not generate any machine code.
+  if ((_encode == NULL) || (encode == NULL)) {
+    fprintf(fp, "  // User did not define an encode section.\n");
+    fprintf(fp, "}\n");
+    return;
+  }
+
+  // Output this instruction's encodings
+  const char *ec_name;
+  bool        user_defined = false;
+  encode->reset();
+  while ((ec_name = encode->encode_class_iter()) != NULL) {
+    fprintf(fp, "  {\n");
+    // Output user-defined encoding
+    user_defined           = true;
+
+    const char *ec_code    = NULL;
+    const char *ec_rep_var = NULL;
+    EncClass   *encoding   = _encode->encClass(ec_name);
+    if (encoding == NULL) {
+      fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name);
+      abort();
+    }
+
+    if (encode->current_encoding_num_args() != encoding->num_args()) {
+      globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+                           inst._ident, encode->current_encoding_num_args(),
+                           ec_name, encoding->num_args());
+    }
+
+    DefineEmitState pending(fp, *this, *encoding, *encode, inst);
+    encoding->_code.reset();
+    encoding->_rep_vars.reset();
+    // Process list of user-defined strings,
+    // and occurrences of replacement variables.
+    // Replacement Vars are pushed into a list and then output
+    while ((ec_code = encoding->_code.iter()) != NULL) {
+      if (!encoding->_code.is_signal(ec_code)) {
+        // Emit pending code
+        pending.emit();
+        pending.clear();
+        // Emit this code section
+        fprintf(fp, "%s", ec_code);
+      } else {
+        // A replacement variable or one of its subfields
+        // Obtain replacement variable from list
+        ec_rep_var  = encoding->_rep_vars.iter();
+        pending.add_rep_var(ec_rep_var);
+      }
+    }
+    // Emit pending code
+    pending.emit();
+    pending.clear();
+    fprintf(fp, "  }\n");
+  } // end while instruction's encodings
+
+  // Check if user stated which encoding to user
+  if (user_defined == false) {
+    fprintf(fp, "  // User did not define which encode class to use.\n");
+  }
+
+  // (3) and (4)
+  fprintf(fp, "}\n");
 }
 
 // ---------------------------------------------------------------------------
@@ -2952,6 +3058,7 @@
     // If there are multiple defs/kills, or an explicit expand rule, build rule
     if( instr->expands() || instr->needs_projections() ||
         instr->has_temps() ||
+        instr->is_mach_constant() ||
         instr->_matrule != NULL &&
         instr->num_opnds() != instr->num_unique_opnds() )
       defineExpand(_CPP_EXPAND_file._fp, instr);
@@ -3032,8 +3139,9 @@
     // Ensure this is a machine-world instruction
     if ( instr->ideal_only() ) continue;
 
-    if (instr->_insencode) defineEmit(fp, *instr);
-    if (instr->_size)      defineSize(fp, *instr);
+    if (instr->_insencode)         defineEmit        (fp, *instr);
+    if (instr->is_mach_constant()) defineEvalConstant(fp, *instr);
+    if (instr->_size)              defineSize        (fp, *instr);
 
     // side-call to generate output that used to be in the header file:
     extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file);