src/share/vm/adlc/output_c.cpp
Print this page
rev 5661 : 8003854: PPC64 (part 115): Introduce lateExpand that expands nodes after register allocation.
*** 2486,2496 ****
//(2)
// Print the size
fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size);
// (3) and (4)
! fprintf(fp,"}\n");
}
// defineEmit -----------------------------------------------------------------
void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
InsEncode* encode = inst._insencode;
--- 2486,2602 ----
//(2)
// Print the size
fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size);
// (3) and (4)
! fprintf(fp,"}\n\n");
! }
!
! // Emit late expand function.
! void ArchDesc::defineLateExpand(FILE *fp, InstructForm &inst) {
! InsEncode *ins_encode = inst._insencode;
!
! // Output instruction's lateExpand prototype.
! fprintf(fp, "void %sNode::lateExpand(GrowableArray <Node *> *nodes, PhaseRegAlloc *ra_) {\n",
! inst._ident);
!
! assert((_encode != NULL) && (ins_encode != NULL), "You must define an encode section.");
!
! // Output each operand's offset into the array of registers.
! inst.index_temps(fp, _globalNames);
!
! // Output variables "unsigned idx_<par_name>", Node *n_<par_name> and "MachOpnd *op_<par_name>"
! // for each parameter <par_name> specified in the encoding.
! ins_encode->reset();
! const char *ec_name = ins_encode->encode_class_iter();
! assert(ec_name != NULL, "late expand must specify an encoding");
!
! 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 (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(),
! ec_name, encoding->num_args());
! }
!
! fprintf(fp, " // Access to ins and operands for late expand.\n");
! const int buflen = 2000;
! char idxbuf[buflen]; char *ib = idxbuf; sprintf(ib, "");
! char nbuf [buflen]; char *nb = nbuf; sprintf(nb, "");
! char opbuf [buflen]; char *ob = opbuf; sprintf(ob, "");
!
! encoding->_parameter_type.reset();
! encoding->_parameter_name.reset();
! const char *type = encoding->_parameter_type.iter();
! const char *name = encoding->_parameter_name.iter();
! int param_no = 0;
! for (; (type != NULL) && (name != NULL);
! (type = encoding->_parameter_type.iter()), (name = encoding->_parameter_name.iter())) {
! const char* arg_name = ins_encode->rep_var_name(inst, param_no);
! int idx = inst.operand_position_format(arg_name);
! if (strcmp(arg_name, "constanttablebase") == 0) {
! ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n",
! name, type, arg_name);
! nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name);
! // There is no operand for the constanttablebase.
! } else if (inst.is_noninput_operand(idx)) {
! globalAD->syntax_err(inst._linenum,
! "In %s: you can not pass the non-input %s to a late expand encoding.\n",
! inst._ident, arg_name);
! } else {
! ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n",
! name, idx, type, arg_name);
! nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name);
! ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx);
! }
! param_no++;
! }
! assert(ib < &idxbuf[buflen-1] && nb < &nbuf[buflen-1] && ob < &opbuf[buflen-1], "buffer overflow");
!
! fprintf(fp, "%s", idxbuf);
! fprintf(fp, " Node *n_region = lookup(0);\n");
! fprintf(fp, "%s%s", nbuf, opbuf);
! fprintf(fp, " Compile *C = ra_->C;\n");
!
! // Output this instruction's encodings.
! fprintf(fp, " {");
! const char *ec_code = NULL;
! const char *ec_rep_var = NULL;
! assert(encoding == _encode->encClass(ec_name), "");
!
! DefineEmitState pending(fp, *this, *encoding, *ins_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");
!
! fprintf(fp, "}\n\n");
!
! ec_name = ins_encode->encode_class_iter();
! assert(ec_name == NULL, "Late expand may only have one encoding.");
}
// defineEmit -----------------------------------------------------------------
void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
InsEncode* encode = inst._insencode;
*** 2839,2849 ****
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
emit_position = true;
} else if ( (strcmp(name,"disp") == 0) ) {
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
} else {
! fprintf(fp,"() const { \n");
}
// Check for hexadecimal value OR replacement variable
if( *encoding == '$' ) {
// Replacement variable
--- 2945,2955 ----
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
emit_position = true;
} else if ( (strcmp(name,"disp") == 0) ) {
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
} else {
! fprintf(fp, "() const {\n");
}
// Check for hexadecimal value OR replacement variable
if( *encoding == '$' ) {
// Replacement variable
*** 2889,2898 ****
--- 2995,3006 ----
}
else if( *encoding == '0' && *(encoding+1) == 'x' ) {
// Hex value
fprintf(fp," return %s;\n", encoding);
} else {
+ globalAD->syntax_err(oper._linenum, "In operand %s: Do not support this encode constant: '%s' for %s.",
+ oper._ident, encoding, name);
assert( false, "Do not support octal or decimal encode constants");
}
fprintf(fp," }\n");
if( emit_position && (position != -1) && (oper.num_edges(globals) > 0) ) {
*** 3140,3150 ****
_instructions.reset();
for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
! 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);
--- 3248,3266 ----
_instructions.reset();
for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
! if (instr->_insencode) {
! if (instr->lateExpands()) {
! // Don't write this to _CPP_EXPAND_file, as the code generated calls C-code
! // from code sections in ad file that is dumped to fp.
! defineLateExpand(fp, *instr);
! } else {
! 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);