--- a/hotspot/src/share/vm/adlc/adlparse.cpp Thu Nov 07 11:47:11 2013 +0100
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp Thu Nov 14 19:24:59 2013 -0800
@@ -219,19 +219,21 @@
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, "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, "ins_encode")) ins_encode_parse(*instr);
+ // Parse late expand keyword.
+ 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, "format")) instr->_format = format_parse();
else if (!strcmp(ident, "interface")) {
parse_err(SYNERR, "Instructions do not specify an interface\n");
}
@@ -240,13 +242,14 @@
// 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 {
- parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of an instruction attribute at %s\n", ident);
+ parse_err(SYNERR, "expected one of:\n predicate, match, encode, or the name of"
+ " an instruction attribute at %s\n", ident);
}
}
skipws();
@@ -258,13 +261,17 @@
}
// Check for "Set" form of chain rule
adjust_set_rule(instr);
- if (_AD._pipeline ) {
- if( instr->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);
+ if (_AD._pipeline) {
+ // No pipe required for late expand.
+ 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 )
+ if (!instr->_ins_pipe) {
parse_err(WARN, "No ins_pipe specified for instruction \"%s\"\n", instr->_ident);
+ }
}
}
// Add instruction to tail of instruction list
@@ -2779,11 +2786,13 @@
encoding->add_parameter(opForm->_ident, param);
}
- // Define a MacroAssembler instance for use by the encoding. The
- // name is chosen to match the __ idiom used for assembly in other
- // parts of hotspot and assumes the existence of the standard
- // #define __ _masm.
- encoding->add_code(" MacroAssembler _masm(&cbuf);\n");
+ if (!inst._is_postalloc_expand) {
+ // Define a MacroAssembler instance for use by the encoding. The
+ // name is chosen to match the __ idiom used for assembly in other
+ // parts of hotspot and assumes the existence of the standard
+ // #define __ _masm.
+ encoding->add_code(" MacroAssembler _masm(&cbuf);\n");
+ }
// Parse the following %{ }% block
ins_encode_parse_block_impl(inst, encoding, ec_name);
@@ -2857,7 +2866,8 @@
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;
}
}
@@ -3050,6 +3060,157 @@
inst._insencode = encrule;
}
+//------------------------------postalloc_expand_parse---------------------------
+// Encode rules have the form
+// postalloc_expand( 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::postalloc_expand_parse(InstructForm& inst) {
+ inst._is_postalloc_expand = true;
+
+ // Parse encode class name.
+ skipws(); // Skip whitespace.
+ if (_curchar != '(') {
+ // Check for postalloc_expand %{ form
+ if ((_curchar == '%') && (*(_ptr+1) == '{')) {
+ next_char(); // Skip '%'
+ next_char(); // Skip '{'
+
+ // Parse the block form of postalloc_expand
+ 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.
+ // identifier is optional.
+ if (_curchar != ')') {
+ ec_name = get_ident();
+ if (ec_name == NULL) {
+ parse_err(SYNERR, "Invalid postalloc_expand class name after 'postalloc_expand('.\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 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.
+
+ // Check for ',' or ')' after encoding.
+ skipws(); // Move to character after parameters.
+ if (_curchar != ')') {
+ // Only a ')' is allowed.
+ 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().
+
+ // Debug Stuff.
+ if (_AD._adl_debug > 1) fprintf(stderr, "Instruction postalloc_expand: %s\n", ec_name);
+
+ // Set encode class of this instruction.
+ inst._insencode = encrule;
+}
+
//------------------------------constant_parse---------------------------------
// Parse a constant expression.