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