output_c.cpp revision 4020
2273N/A * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A// output_c.cpp - Class CPP file output routines for architecture definition 0N/A// Utilities to characterize effect statements 0N/A// Define an array containing the machine register names, strings. 0N/A fprintf(
fp,
"// An array of character pointers to machine register names.\n");
0N/A fprintf(
fp,
"const char *Matcher::regName[REG_COUNT] = {\n");
0N/A // Output the register name for each register in the allocation classes 0N/A // Finish defining enumeration 0N/A fprintf(
fp,
"// An array of character pointers to machine register names.\n");
0N/A fprintf(
fp,
"const VMReg OptoReg::opto2vm[REG_COUNT] = {\n");
0N/A // Finish defining array 0N/A fprintf(
fp,
" OptoReg::Name OptoReg::vm2opto[ConcreteRegisterImpl::number_of_registers];\n");
0N/A// Define an array containing the machine register encoding values 0N/A fprintf(
fp,
"// An array of the machine register encode values\n");
0N/A fprintf(
fp,
"const unsigned char Matcher::_regEncode[REG_COUNT] = {\n");
0N/A // Output the register encoding for each register in the allocation classes 0N/A // Output known constants in hex char format (backward compatibility). 0N/A // Finish defining enumeration 0N/A }
// Done defining array 0N/A// Output an enumeration of register class names 0N/A // Output an enumeration of register class names 0N/A // Finish defining enumeration 0N/A// Declare an enumeration of user-defined register classes 0N/A// and a list of register masks, one for each class. 0N/A // Build enumeration of user-defined register classes. 0N/A // Generate a list of register masks, one for each class. 0N/A// Generate an enumeration of user-defined register classes 0N/A// and a list of register masks, one for each class. 0N/A // Generate a list of register masks, one for each class. 0N/A// Compute an index for an array in the pipeline_reads_NNN arrays 0N/A // See if the count is zero 0N/A // See if the same string is in the table 0N/A // No, add it to the table 0N/A fprintf(
fp_cpp,
"static const enum machPipelineStages pipeline_reads_%03d[%d] = {\n%s};\n\n",
0N/A// Compute an index for an array in the pipeline_res_stages_NNN arrays 0N/A // Compute the length needed for the resource list 0N/A // Allocate space for the resource list 0N/A // See if the same string is in the table 0N/A // No, add it to the table 0N/A fprintf(
fp_cpp,
"static const enum machPipelineStages pipeline_res_stages_%03d[%d] = {\n%s};\n\n",
0N/A// Compute an index for an array in the pipeline_res_cycles_NNN arrays 0N/A // Pre-compute the string length 0N/A // Allocate space for the resource list 0N/A // See if the same string is in the table 0N/A // No, add it to the table 0N/A//typedef unsigned long long uint64_t; 0N/A// Compute an index for an array in the pipeline_res_mask_NNN arrays 0N/A // Pre-compute the string length 0N/A // Allocate space for the resource list 0N/A // See if the same string is in the table 0N/A // No, add it to the table 0N/A fprintf(
fp_cpp,
"static const Pipeline_Use_Element pipeline_res_mask_%03d[%d] = {\n%s};\n\n",
0N/A//delete [] res_masks; 0N/A fprintf(
fp_cpp,
" // assert(false, \"pipeline functionality is not defined\");\n");
0N/A fprintf(
fp_cpp,
"//------------------Pipeline Methods-----------------------------------------\n");
0N/A fprintf(
fp_cpp,
"uint Pipeline::functional_unit_latency(uint start, const Pipeline *pred) const {\n");
0N/A fprintf(
fp_cpp,
" tty->print(\"# functional_unit_latency: start == %%d, this->exclusively == 0x%%03x, pred->exclusively == 0x%%03x\\n\", start, resourcesUsedExclusively(), pred->resourcesUsedExclusively());\n");
0N/A fprintf(
fp_cpp,
" uint mask = resourcesUsedExclusively() & pred->resourcesUsedExclusively();\n");
0N/A fprintf(
fp_cpp,
" tty->print(\"# functional_unit_latency: mask == 0x%%x\\n\", mask);\n");
0N/A fprintf(
fp_cpp,
" const Pipeline_Use_Element *predUse = pred->resourceUseElement(i);\n");
0N/A fprintf(
fp_cpp,
" const Pipeline_Use_Element *currUse = resourceUseElement(j);\n");
0N/A fprintf(
fp_cpp,
"// The following two routines assume that the root Pipeline_Use entity\n");
0N/A fprintf(
fp_cpp,
"// start is relative to the current cycle; used for latency-based info\n");
0N/A fprintf(
fp_cpp,
"uint Pipeline_Use::full_latency(uint delay, const Pipeline_Use &pred) const {\n");
0N/A fprintf(
fp_cpp,
" // Multiple possible functional units, choose first unused one\n");
0N/A fprintf(
fp_cpp,
" // Multiple possible functional units, choose first unused one\n");
0N/A fprintf(
fp_cpp,
"uint Pipeline::operand_latency(uint opnd, const Pipeline *pred) const {\n");
0N/A fprintf(
fp_cpp,
" tty->print(\"# operand_latency(%%d), _read_stage_count = %%d\\n\", opnd, _read_stage_count);\n");
0N/A fprintf(
fp_cpp,
" if (pred->hasFixedLatency())\n return (pred->fixedLatency());\n\n");
0N/A fprintf(
fp_cpp,
" // If this is not an operand, then assume a dependence with 0 latency\n");
0N/A fprintf(
fp_cpp,
" tty->print(\"# operand_latency: writeStage=%%s readStage=%%s, opnd=%%d\\n\", stageName(writeStage), stageName(readStage), opnd);\n");
0N/A fprintf(
fp_cpp,
" if (writeStage == stage_undefined || readStage == stage_undefined)\n");
0N/A fprintf(
fp_cpp,
"Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
0N/A fprintf(
fp_cpp,
"Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
0N/A fprintf(
fp_cpp,
"Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
0N/A fprintf(
fp_cpp,
"Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
0N/A fprintf(
fp_cpp,
"void Pipeline_Use_Cycle_Mask::Or(const Pipeline_Use_Cycle_Mask &in2) {\n ");
0N/A /* Get the length of all the resource names */ 0N/A // Create the pipeline class description 0N/A fprintf(
fp_cpp,
"static const Pipeline pipeline_class_Zero_Instructions(0, 0, true, 0, 0, false, false, false, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n");
0N/A fprintf(
fp_cpp,
"static const Pipeline pipeline_class_Unknown_Instructions(0, 0, true, 0, 0, false, true, true, false, NULL, NULL, NULL, Pipeline_Use(0, 0, 0, NULL));\n\n");
0N/A fprintf(
fp_cpp,
"const Pipeline_Use Pipeline_Use::elaborated_use(0, 0, %d, (Pipeline_Use_Element *)&elaborated_elements[0]);\n\n",
0N/A // Scan the operands, looking for last output stage and number of inputs 0N/A // Create the list of stages for the operands that are read 0N/A // Note that we will build a NameList to reduce the number of copies 0N/A // Process the Resources 0N/A // Create the pipeline class description 0N/A fprintf(
fp_cpp,
", %d, %s, %d, %d, %s, %s, %s, %s,\n",
0N/A fprintf(
fp_cpp,
" (enum machPipelineStages * const) pipeline_res_stages_%03d,\n",
0N/A // Generate the Node::latency method if _pipeline defined 0N/A fprintf(
fp_cpp,
"//------------------Inter-Instruction Latency--------------------------------\n");
0N/A fprintf(
fp_cpp,
" // if either node does not have pipeline info, use default\n");
0N/A fprintf(
fp_cpp,
" if (predpipe->hasFixedLatency())\n return predpipe->fixedLatency();\n\n");
0N/A fprintf(
fp_cpp,
" if (i < j)\n return currpipe->functional_unit_latency(%d, predpipe);\n\n",
0N/A fprintf(
fp_cpp,
" return currpipe->functional_unit_latency(delta, predpipe);\n");
0N/A fprintf(
fp_cpp,
" // assert(false, \"pipeline functionality is not defined\");\n");
0N/A // Output the list of nop nodes 0N/A fprintf(
fp_cpp,
"// Descriptions for emitting different functional unit nops\n");
0N/A // See if the same string is in the table 0N/A fprintf(
fp_cpp,
" tty->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n");
0N/A fprintf(
fp_cpp,
" tty->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n");
0N/A// --------------------------------------------------------------------------- 0N/A//------------------------------Utilities to build Instruction Classes-------- 0N/A// --------------------------------------------------------------------------- 0N/A fprintf(
fp,
"const RegMask &%sNode::out_RegMask() const { return (%s); }\n",
0N/A// Scan the peepmatch and output a test for each instruction 0N/A // If this is not a placeholder 0N/A // Define temporaries 'inst#', based on parent and parent's input index 0N/A // When not the root 0N/A // Test we have the correct instruction by comparing the rule 0N/A // Check that user did not try to constrain a placeholder 0N/A "fatal(): Can not constrain a placeholder instruction");
0N/A// Scan the peepmatch and output a test for each instruction 0N/A // If this is not a placeholder 0N/A // Define temporaries 'inst#', based on parent and parent's input index 0N/A fprintf(
fp,
" // Identify previous instruction if inside this block\n");
0N/A // When not the root 0N/A // Test we have the correct instruction by comparing the rule. 603N/A fprintf(
fp,
" matches = matches && (inst%d != NULL) && (inst%d->rule() == %s_rule);\n",
0N/A // Check that user did not try to constrain a placeholder 0N/A "fatal(): Can not constrain a placeholder instruction");
0N/A// Build mapping for register indices, num_edges to input 0N/A // If this is not a placeholder 0N/A // Define temporaries 'inst#', based on self's inst_position 0N/A// Generate tests for the constraints 0N/A // Build mapping from num_edges to local variables 0N/A // Build constraint tests 0N/A // indentation and connecting '&&' 0N/A // Only have '==' relation implemented 0N/A // Access info on the instructions whose operands are compared 0N/A // Access info on the operands being compared 0N/A // Access info on the instructions whose operands are compared 0N/A // Access info on the operands being compared 0N/A }
else {
// Else match register 0N/A // assert( false, "should be a register" ); 0N/A // Check for equivalence 0N/A // fprintf(fp, "phase->eqv( "); 0N/A // fprintf(fp, "inst%d->in(%d+%d) /* %s */, inst%d->in(%d+%d) /* %s */", 0N/A // left_index, left_op_base, left_op_index, left_op, 0N/A // right_index, right_op_base, right_op_index, right_op ); 0N/A // fprintf(fp, ")"); 0N/A // Check that they are allocated to the same register 0N/A // Need parameter for index position if not result operand 0N/A // Must have index into operands 0N/A fprintf(
fp,
"(inst%d->_opnds[%d]->reg(ra_,inst%d%s) /* %d.%s */",
0N/A // Must have index into operands 0N/A fprintf(
fp,
"/* %d.%s */ inst%d->_opnds[%d]->reg(ra_,inst%d%s)",
0N/A // Compare the '->constant()' values 0N/A // Compare 'base', 'index', 'scale', and 'disp' 0N/A fprintf(
fp,
" (inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d) /* %d.%s$$base */",
0N/A fprintf(
fp,
"/* %d.%s$$base */ inst%d->_opnds[%d]->base(ra_,inst%d,inst%d_idx%d)) &&\n",
0N/A fprintf(
fp,
" (inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d) /* %d.%s$$index */",
0N/A fprintf(
fp,
"/* %d.%s$$index */ inst%d->_opnds[%d]->index(ra_,inst%d,inst%d_idx%d)) &&\n",
0N/A fprintf(
fp,
" (inst%d->_opnds[%d]->scale() /* %d.%s$$scale */",
0N/A fprintf(
fp,
"/* %d.%s$$scale */ inst%d->_opnds[%d]->scale()) &&\n",
0N/A fprintf(
fp,
" (inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d) /* %d.%s$$disp */",
0N/A fprintf(
fp,
"/* %d.%s$$disp */ inst%d->_opnds[%d]->disp(ra_,inst%d,inst%d_idx%d))\n",
0N/A // Compare the condition code being tested 0N/A // Advance to next constraint 0N/A// // EXPERIMENTAL -- TEMPORARY code 0N/A// static Form::DataType get_operand_type(FormDict &globals, InstructForm *instr, const char *op_name ) { 0N/A// int op_index = instr->operand_position(op_name, Component::USE); 0N/A// if( op_index == -1 ) { 0N/A// op_index = instr->operand_position(op_name, Component::DEF); 0N/A// if( op_index == -1 ) { 0N/A// op_index = instr->operand_position(op_name, Component::USE_DEF); 0N/A// assert( op_index != NameList::Not_in_list, "Did not find operand in instruction"); 0N/A// ComponentList components_right = instr->_components; 0N/A// char *right_comp_type = components_right.at(op_index)->_type; 0N/A// OpClassForm *right_opclass = globals[right_comp_type]->is_opclass(); 0N/A// Form::InterfaceType right_interface_type = right_opclass->interface_type(globals); 0N/A// Construct the new sub-tree 0N/A fprintf(
fp,
" // IF instructions and constraints matched\n");
0N/A // Get the root of the new sub-tree 0N/A // Then install the use-operands for the new sub-tree 0N/A // preplace->reset(); // reset breaks iteration 0N/A // find the name of the OperandForm from the local name 0N/A // Initial setup of new instruction 0N/A // Add control edge for this node 0N/A // Add unmatched edges from root of match tree 603N/A fprintf(
fp,
" root->add_req(inst%d->in(%d)); // unmatched ideal edge\n",
0N/A // If new instruction captures bottom type 0N/A // Get bottom type from instruction whose result we are replacing 0N/A // Define result register and result operand 0N/A // Do not have ideal edges for constants after matching 603N/A fprintf(
fp,
" for( unsigned x%d = inst%d_idx%d; x%d < inst%d_idx%d; x%d++ )\n",
0N/A fprintf(
fp,
" // no ideal edge for constants after matching\n");
0N/A // Replacing subtree with empty-tree 0N/A // Return the new sub-tree 0N/A// Define the Peephole method for an instruction node 0N/A // Generate Peephole function header 0N/A fprintf(
fp,
"MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n",
node->
_ident);
0N/A // Identify the maximum instruction position, 0N/A // generate temporaries that hold current instruction 0N/A // MachNode *inst0 = NULL; 0N/A // MachNode *instMAX = NULL; 0N/A // For each peephole rule in architecture description 0N/A // Construct a test for the desired instruction sub-tree 0N/A // then check the constraints 0N/A // If these match, Generate the new subtree 0N/A // Root of this peephole is the current MachNode 0N/A assert(
true,
// %%name?%% strcmp( node->_ident, pmatch->name(0) ) == 0, 0N/A "root of PeepMatch does not match instruction");
0N/A // Make each peephole rule individually selectable 0N/A // Scan the peepmatch and output a test for each instruction 0N/A // Check constraints and build replacement inside scope 0N/A // Generate tests for the constraints 0N/A // Construct the new sub-tree 0N/A // End of scope for this peephole's constraints 0N/A // Closing brace '}' to make each peephole rule individually selectable 0N/A fprintf(
fp,
" return NULL; // No peephole rules matched\n");
0N/A// Define the Expand method for an instruction node 0N/A unsigned cnt = 0;
// Count nodes we have expand into 0N/A // Generate Expand function header 0N/A // Generate expand code 0N/A // If necessary, generate any operands created in expand rule 0N/A assert(
frm,
"Invalid entry in new operands list of expand rule");
0N/A // Generate the temps to use for DAG building 0N/A // Build mapping from num_edges to local variables 0N/A fprintf(
fp,
" unsigned num%d = opnd_array(%d)->num_edges();\n",i,i);
0N/A // Build a mapping from operand index to input edges 1203N/A // The order in which the memory input is added to a node is very 113N/A // strange. Store nodes get a memory input before Expand is 1203N/A // called and other nodes get it afterwards or before depending on 1203N/A // match order so oper_input_base is wrong during expansion. This 1203N/A // code adjusts it so that expansion will work correctly. 1203N/A fprintf(
fp,
" idx0--; // Adjust base because memory edge hasn't been inserted yet\n");
0N/A // Declare variable to hold root of expansion 0N/A // Iterate over the instructions 'node' expands into 0N/A // Build the node for the instruction 0N/A // Add control edge for this node 0N/A // Build the operand for the value this node defines. 0N/A // Grab the InstructForm for the new instruction 4020N/A // Fill in the bottom_type where requested 0N/A fprintf(
fp,
" n%d->set_opnd_array(0, state->MachOperGenerator( %s, C ));\n",
0N/A // get the formal operand NameList 0N/A // Handle any memory operand 0N/A "expand rule member needs memory but top-level inst doesn't have any" );
0N/A // Iterate over the new instruction's operands 0N/A // Use 'parameter' at current position in list of new instruction's formals 0N/A // instead of 'opid' when looking up info internal to new_inst 0N/A // Check for an operand which is created in the expand rule 0N/A // If there is no use of the created operand, just skip it 0N/A //Copy the operand from the original made above 0N/A fprintf(
fp,
" n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n",
0N/A // Check for who defines this operand & add edge if needed 0N/A // Use operand name to get an index into instruction component list 0N/A // ins = (InstructForm *) _globalNames[new_id]; 415N/A // For the add_req calls below to work correctly they need 415N/A // to added in the same order that a match would add them. 415N/A // This means that they would need to be in the order of 415N/A // the components list instead of the formal parameters. 415N/A // This is a sort of hidden invariant that previously 415N/A // wasn't checked and could lead to incorrectly 0N/A // Copy the operand from the ExpandNode to the new node 0N/A fprintf(
fp,
" n%d->set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n",
0N/A // For each operand add appropriate input edges by looking at tmp's 0N/A // Grab corresponding edges from ExpandNode and insert them here 0N/A // This value is generated by one of the new instructions 0N/A // Update the DAG tmp's for values defined by this instruction 0N/A // If this operand is a definition in either an effects rule 0N/A // Update the temp associated with this operand 0N/A // Instruction defines a value but user did not declare it 0N/A // in the 'effect' clause 0N/A }
// done iterating over a new instruction's operands 0N/A // Invoke Expand() for the newly created instruction. 0N/A }
// done iterating over new instructions 0N/A }
// done generating expand rule 2126N/A // Generate projections for instruction's additional DEFs and KILLs 2126N/A // Get string representing the MachNode that projections point at 2126N/A // Generate the projections 2126N/A // Examine each component to see if it is a DEF or KILL 2126N/A // Skip the first component, if already handled as (SET dst (...)) 2126N/A // For kills, the choice of projection numbers is arbitrary 2126N/A // Lookup register class associated with operand type 2126N/A // Define the variable "def" to hold new MachProjNodes 2126N/A fprintf(
fp,
" def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n",
2126N/A // The operand for TEMP is already constructed during 2126N/A // this mach node construction, see buildMachNode(). 2126N/A // int idx = node->operand_position_format(comp->_name); 2126N/A // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", 2126N/A // idx, machOperEnum(op->_ident)); 2126N/A assert(
false,
"can't have temps which aren't registers");
2126N/A // Define the variable "kill" to hold new MachProjNodes 0N/A // Remove duplicated operands and inputs which use the same name. 0N/A // Seach through match operands for the same name usage. 0N/A // Build mapping from num_edges to local variables 0N/A fprintf(
fp,
" unsigned num%d = opnd_array(%d)->num_edges();\n",i,i);
0N/A // Build a mapping from operand index to input edges 0N/A // Skip first unique operands. 0N/A // Replace not unique operands with next unique operands. 0N/A // unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique. 0N/A fprintf(
fp,
" set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n",
0N/A // delete not unique edges here 0N/A // delete the rest of edges 1915N/A // If the node is a MachConstantNode, insert the MachConstantBaseNode edge. 1915N/A // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input). 0N/A//------------------------------Emit Routines---------------------------------- 0N/A// Special classes and routines for defining node emit routines which output 0N/A// target specific instruction object encodings. 0N/A// Define the ___Node::emit() routine 0N/A// (1) void ___Node::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { 0N/A// (2) // ... encoding defined by user 0N/A // Temporaries that describe current operand 0N/A // Stable state, set by constructor 0N/A // Track necessary state when identifying a replacement variable 0N/A // A replacement variable or one of its subfields 0N/A // Obtain replacement variable from list 0N/A // A replacement variable, '$' prefix 0N/A // check_rep_var( rep_var ); 0N/A "'primary', 'secondary' and 'tertiary' don't follow operand.");
1915N/A "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
0N/A // Lookup its position in parameter list 0N/A "Replacement variable %s not found in enc_class %s.\n",
0N/A // Lookup the corresponding ins_encode parameter 0N/A "Parameter %s not passed to enc_class %s from instruct %s.\n",
0N/A // Check if instruction's actual parameter is a local name in the instruction 0N/A // Note: assert removed to allow constant and symbolic parameters 0N/A // assert( opc, "replacement variable was not found in local names"); 0N/A // Lookup the index position iff the replacement variable is a localName 0N/A // This is a local in the instruction 0N/A // Update local state info. 0N/A // Do not support consecutive operands. 0N/A // Instruction provided a constant expression 0N/A // Check later that encoding specifies $$$constant to resolve as constant 0N/A // Instruction provided an opcode: "primary", "secondary", "tertiary" 0N/A // Check later that encoding specifies $$$constant to resolve as constant 0N/A // Instruction provided a literal register name for this parameter 0N/A // Check that encoding specifies $$$reg to resolve.as register. 0N/A // Check for unimplemented functionality before hard failure 0N/A }
// done checking which operand this is. 0N/A // A subfield variable, '$$' prefix 0N/A // Check for fields that may require relocation information. 0N/A // Then check that literal register parameters are accessed with 'reg' or 'constant' 0N/A // Only have an operand class, generate run-time check for relocation 0N/A // Do precise check on operand: is it a ConP or not 0N/A // Check interface for value of displacement 0N/A "$disp can only follow memory interface operand");
0N/A "$disp can only follow memory interface operand");
0N/A // MemInterface::disp contains a replacement variable, 0N/A // Check if this matches a ConP 0N/A // Lookup replacement variable, in operand's component list 0N/A // Lookup operand form for replacement variable's type 0N/A assert(
op,
"Attempting to emit a non-register or non-constant");
0N/A // Check if this is a constant 0N/A // Check which constant this name maps to: _c0, _c1, ..., _cn 0N/A // const int idx = _operand.constant_position(_AD.globalNames(), comp); 0N/A // assert( idx != -1, "Constant component not found in operand"); 0N/A // No longer true that idealP is always an oop 0N/A // The only non-constant allowed access to disp is an operand sRegX in a stackSlotX 0N/A assert(
false,
"fatal(); Only stackSlots can access a non-constant using 'disp'");
0N/A }
// finished with precise check of operand for relocation. 0N/A }
// finished with subfield variable 0N/A // Check operand for type of constant 0N/A // No longer true that idealP is always an oop 0N/A // // _must_reloc = true; 0N/A // No relocation information needed 0N/A // User-provided literals may not require relocation information !!!!! 0N/A // Calls containing labels require relocation 0N/A // literal register parameter must be accessed as a 'reg' field. 0N/A assert(
false,
"invalid access to literal register parameter");
0N/A // literal constant parameters must be accessed as a 'constant' field 0N/A assert(
false,
"invalid access to literal constant parameter");
0N/A // Handle subfield and replacement variables. 0N/A // Check for emit prefix, '$$emit32' 0N/A // Update state for replacement variables 0N/A // A replacement variable or one of its subfields 0N/A // Obtain replacement variable from list 0N/A // const char *ec_rep_var = encoding->_rep_vars.iter(); 0N/A // A subfield variable, '$$' prefix 624N/A // skip trailing $Address 624N/A // A replacement variable, '$' prefix 624N/A // handle $rev_var$$base$$Register and $rev_var$$index$$Register by 624N/A // producing as_Register(opnd_array(#)->base(ra_,this,idx1)). 624N/A // emit the operand reference 624N/A // handle base or index 0N/A // "emit_d32_reloc(" or "emit_hi_reloc" or "emit_lo_reloc" 0N/A // Emit the function name when generating an emit function 0N/A // In general, relocatable isn't known at compiler compile time. 0N/A // Check results of prior scan 0N/A // Definitely don't need relocation information 0N/A // Must emit relocation information 0N/A // Emit RUNTIME CHECK to see if value needs relocation info 0N/A // If emitting a relocatable address, use 'emit_d32_reloc' 0N/A "Must be emitting either a displacement or a constant");
0N/A // Relocation of 16-bit values is not supported 0N/A // No relocation done for 16-bit values 0N/A // Relocation of 8-bit values is not supported 0N/A // No relocation done for 8-bit values 0N/A // Not an emit# command, just output the replacement string. 0N/A // Get ready for next state collection. 0N/A // recognizes names which represent MacroAssembler register types 0N/A // and return the conversion function to build them from OptoReg 0N/A // A subfield variable, '$$subfield' 0N/A // $reg form or the $Register MacroAssembler type conversions 0N/A "Must use this subfield after operand");
0N/A // Add parameter for index position, if not result operand 0N/A // Register literal has already been sent to output file, nothing more needed 0N/A "Must use this subfield after operand");
0N/A "Must use this subfield after operand");
0N/A // Cosntant literal has already been sent to output file, nothing more needed 0N/A // A replacement variable, originally '$' 415N/A "Missing $%s opcode definition in %s, used by encoding %s\n",
1915N/A fprintf(
_fp,
"as_Register(ra_->get_encode(in(mach_constant_base_node_input())))");
1915N/A fprintf(
_fp,
"InternalAddress(__ code()->consts()->start() + constant_offset())");
0N/A // Lookup its position in parameter list 0N/A "Replacement variable %s not found in enc_class %s.\n",
0N/A // Lookup the corresponding ins_encode parameter 0N/A // Check if instruction's actual parameter is a local name in the instruction 0N/A // Note: assert removed to allow constant and symbolic parameters 0N/A // assert( opc, "replacement variable was not found in local names"); 0N/A // Lookup the index position iff the replacement variable is a localName 0N/A // This operand isn't a normal input so printing it is done 0N/A // Output the emit code for this operand 0N/A "Previous emit $operand does not match current");
0N/A // else check if it is a constant expression 0N/A // Removed following assert to allow primitive C types as arguments to encodings 0N/A // assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter"); 0N/A // else check if "primary", "secondary", "tertiary" 415N/A "Missing $%s opcode definition in %s\n",
0N/A // Instruction provided a literal register name for this parameter 0N/A // Check that encoding specifies $$$reg to resolve.as register. 0N/A // Check for unimplemented functionality before hard failure 0N/A};
// end class DefineEmitState 0N/A // Output instruction's emit prototype 0N/A fprintf(
fp,
"uint %sNode::size(PhaseRegAlloc *ra_) const {\n",
1915N/A// defineEmit ----------------------------------------------------------------- 0N/A // Output instruction's emit prototype 0N/A // If user did not define an encode section, 0N/A // provide stub that does not generate any machine code. 0N/A fprintf(
fp,
" // User did not define an encode section.\n");
0N/A // Save current instruction's starting address (helps with relocation). 1915N/A // For MachConstantNodes which are ideal jump nodes, fill the jump table. 1915N/A fprintf(
fp,
" ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
0N/A // Output each operand's offset into the array of registers. 0N/A // Output this instruction's encodings 0N/A // Output user-defined encoding 0N/A // Process list of user-defined strings, 0N/A // and occurrences of replacement variables. 0N/A // Replacement Vars are pushed into a list and then output 0N/A // Emit pending code 0N/A // Emit this code section 0N/A // A replacement variable or one of its subfields 0N/A // Obtain replacement variable from list 0N/A // Emit pending code 0N/A }
// end while instruction's encodings 0N/A // Check if user stated which encoding to user 0N/A fprintf(
fp,
" // User did not define which encode class to use.\n");
1915N/A// defineEvalConstant --------------------------------------------------------- 1915N/A // Output instruction's emit prototype 2957N/A // For ideal jump nodes, add a jump-table entry. 2957N/A fprintf(
fp,
" _constant = C->constant_table().add_jump_table(this);\n");
1915N/A // If user did not define an encode section, 1915N/A // provide stub that does not generate any machine code. 1915N/A // Output this instruction's encodings 1915N/A // Output user-defined encoding 1915N/A // Process list of user-defined strings, 1915N/A // and occurrences of replacement variables. 1915N/A // Replacement Vars are pushed into a list and then output 1915N/A // A replacement variable or one of its subfields 1915N/A // Obtain replacement variable from list 1915N/A }
// end while instruction's encodings 1915N/A // Check if user stated which encoding to user 0N/A// --------------------------------------------------------------------------- 0N/A//--------Utilities to build MachOper and MachNode derived Classes------------ 0N/A// --------------------------------------------------------------------------- 0N/A//------------------------------Utilities to build Operand Classes------------ 0N/A fprintf(
fp,
"const RegMask *%sOper::in_RegMask(int index) const {\n",
0N/A // Assert that the index is in range. 0N/A fprintf(
fp,
" assert(0 <= index && index < %d, \"index out of range\");\n",
0N/A // Figure out if all RegMasks are the same. 0N/A // Return the sole RegMask. 0N/A fprintf(
fp,
" return &(Compile::current()->FIRST_STACK_mask());\n");
0N/A // Build a switch statement to return the desired mask. 0N/A// generate code to create a clone for a class derived from MachOper 0N/A// (0) MachOper *MachOperXOper::clone(Compile* C) const { 0N/A// (1) return new (C) MachXOper( _ccode, _c0, _c1, ..., _cn); 0N/A // Check for constants that need to be copied over 0N/A // generate parameters for constants 0N/A fprintf(
fp,
"uint %sOper::cmp( const MachOper &oper ) const { return opcode() == oper.opcode(); }\n",
operand);
0N/A// Helper functions for bug 4796752, abstracted with minimal modification 0N/A// from define_oper_interface() 0N/A // Check for replacement variable 0N/A // Replacement variable 0N/A // Lookup replacement variable, rep_var, in operand's component list 0N/A // Lookup operand form for replacement variable's type 0N/A assert(
op,
"Attempting to emit a non-register or non-constant");
0N/A // Check for replacement variable 0N/A // Replacement variable 0N/A // Lookup replacement variable, rep_var, in operand's component list 0N/A // Lookup operand form for replacement variable's type 0N/A assert(
op,
"Attempting to emit a non-register or non-constant");
0N/A // Check that this is a constant and find constant's index: 0N/A // Check that this is a register 0N/A // Check that this is a constant pointer 0N/A// Define a MachOper interface methods 0N/A // Generate access method for base, index, scale, disp, ... 0N/A fprintf(
fp,
"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
0N/A fprintf(
fp,
"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
0N/A // Check for hexadecimal value OR replacement variable 0N/A // Replacement variable 0N/A // Lookup replacement variable, rep_var, in operand's component list 0N/A // Lookup operand form for replacement variable's type 0N/A assert(
op,
"Attempting to emit a non-register or non-constant");
0N/A // Check that this is a register or a constant and generate code: 0N/A // StackSlot for an sReg comes either from input node or from self, when idx==0 0N/A fprintf(
fp,
" // Access register number for input operand\n");
0N/A fprintf(
fp,
" return ra_->reg2offset(ra_->get_reg_first(node->in(idx)));/* sReg */\n");
0N/A fprintf(
fp,
" return ra_->reg2offset(ra_->get_reg_first(node));/* sReg */\n");
0N/A // Check which constant this name maps to: _c0, _c1, ..., _cn 0N/A assert(
idx != -
1,
"Constant component not found in operand");
0N/A // Output code for this constant, type dependent. 0N/A assert(
false,
"Attempting to emit a non-register or non-constant");
0N/A assert(
false,
"Do not support octal or decimal encode constants");
0N/A // Found a memory access using a constant pointer for a displacement 0N/A // and a base register containing an integer offset. 0N/A // In this case the base and disp are reversed with respect to what 0N/A // is expected by MachNode::get_base_and_disp() and MachNode::adr_type(). 0N/A // Provide a non-NULL return for disp_as_type() that will allow adr_type() 0N/A // to correctly compute the access type for alias analysis. 0N/A // See BugId 4796752, operand indOffset32X in i486.ad 0N/A fprintf(
fp,
" virtual const TypePtr *disp_as_type() const { return _c%d; }\n",
idx);
0N/A// Construct the method to copy _idx, inputs and operands to new node. 0N/A fprintf(
fp_cpp,
"void MachNode::fill_new_machnode( MachNode* node, Compile* C) const {\n");
0N/A fprintf(
fp_cpp,
" // This architecture does not have cisc or short branch instructions\n");
0N/A // New node must use same node index for access through allocator's tables 0N/A // Copy machine-independent inputs 0N/A // Copy machine operands to new MachNode 0N/A fprintf(
fp_cpp,
" assert( node->num_opnds() == (uint)nopnds, \"Must have same number of operands\");\n");
0N/A//------------------------------defineClasses---------------------------------- 0N/A// Define members of MachNode and MachOper classes based on 0N/A// operand and instruction lists 0N/A // Define the contents of an array containing the machine register names 0N/A // Define an array containing the machine register encoding values 0N/A // Generate an enumeration of user-defined register classes 0N/A // and a list of register masks, one for each class. 0N/A // Only define the RegMask value objects in the expand file. 0N/A // Declare each as an extern const RegMask ...; in ad_<arch>.hpp 0N/A // build_register_masks(fp); 0N/A // Define the pipe_classes 0N/A // Generate Machine Classes for each operand defined in AD file 0N/A fprintf(
fp,
"//------------------Define classes derived from MachOper---------------------\n");
0N/A // Iterate through all operands 0N/A // Ensure this is a machine-world instruction 0N/A // The declaration of labelOper is in machine-independent file: machnode 0N/A // // Currently all XXXOper::Hash() methods are identical (990820) 0N/A // define_hash(fp, oper->_ident); 0N/A // // Currently all XXXOper::Cmp() methods are identical (990820) 0N/A // define_cmp(fp, oper->_ident); 0N/A // The declaration of methodOper is in machine-independent file: machnode 0N/A // // Currently all XXXOper::Hash() methods are identical (990820) 0N/A // define_hash(fp, oper->_ident); 0N/A // // Currently all XXXOper::Cmp() methods are identical (990820) 0N/A // define_cmp(fp, oper->_ident); 0N/A // // Currently all XXXOper::Hash() methods are identical (990820) 0N/A // define_hash(fp, oper->_ident); 0N/A // // Currently all XXXOper::Cmp() methods are identical (990820) 0N/A // define_cmp(fp, oper->_ident); 0N/A // side-call to generate output that used to be in the header file: 0N/A // Generate Machine Classes for each instruction defined in AD file 0N/A fprintf(
fp,
"//------------------Define members for classes derived from MachNode----------\n");
0N/A // Output the definitions for out_RegMask() // & kill_RegMask() 0N/A // Ensure this is a machine-world instruction 0N/A // Output the definitions for expand rules & peephole rules 0N/A // Ensure this is a machine-world instruction 0N/A // If there are multiple defs/kills, or an explicit expand rule, build rule 0N/A // If there is an explicit peephole rule, build it 0N/A // Output code to convert to the cisc version, if applicable 0N/A // Output code to convert to the short branch version, if applicable 0N/A // Construct the method called by cisc_version() to copy inputs and operands. 0N/A // Output the definitions for labels 0N/A // Ensure this is a machine-world instruction 0N/A // Access the fields for operand Label 0N/A fprintf(
fp,
" labelOper* oper = (labelOper*)(opnd_array(%d));\n",
0N/A // Output the definitions for methods 0N/A // Ensure this is a machine-world instruction 0N/A // Access the fields for operand Label 0N/A // Access the method's address 0N/A fprintf(
fp,
" ((methodOper*)opnd_array(%d))->_method = method;\n",
0N/A // Define this instruction's number of relocation entries, base is '0' 0N/A // Output the definition for number of relocation entries 0N/A // Output the definitions for code generation 0N/A // address ___Node::emit(address ptr, PhaseRegAlloc *ra_) const { 0N/A // // ... encoding defined by user 0N/A // Ensure this is a machine-world instruction 0N/A // side-call to generate output that used to be in the header file: 0N/A // Output the definitions for alias analysis 0N/A // Ensure this is a machine-world instruction 0N/A // Analyze machine instructions that either USE or DEF memory. 0N/A // Some guys kill all of memory 0N/A // Get the length of the longest identifier 0N/A // Emit specifically for Node(s) 0N/A // Output the definitions for machine node specific pipeline data 0N/A // Output the definitions for instruction pipeline static data references 0N/A// -------------------------------- maps ------------------------------------ 0N/A// Information needed to generate the ReduceOp mapping for the DFA 0N/A // Most operands without match rules, e.g. eFlagsReg, do not have a result operand 0N/A // operand stackSlot does not have a match rule, but produces a stackSlot 0N/A// Information needed to generate the LeftOp mapping for the DFA 0N/A// Information needed to generate the RightOp mapping for the DFA 0N/A// Information needed to generate the Rule names for the DFA 0N/A// Information needed to generate the swallowed mapping for the DFA 0N/A// Information needed to generate the decision array for instruction chain rule 0N/A//---------------------------build_map------------------------------------ 0N/A// Build mapping from enumeration for densely packed operands 0N/A// TO result and child types. 0N/A // Construct this mapping 0N/A // Output the mapping for operands 0N/A // Ensure this is a machine-world instruction 0N/A // Generate the entry for this opcode 0N/A // Place all user-defined operand classes into the mapping 0N/A // Place all internally defined operands into the mapping 0N/A // Place all user-defined instructions into the mapping 0N/A // Output all simple instruction chain rules first 0N/A // Ensure this is a machine-world instruction 0N/A // Ensure this is a machine-world instruction 0N/A // Output all instructions that are NOT simple chain rules 0N/A // Ensure this is a machine-world instruction 0N/A // Ensure this is a machine-world instruction 0N/A // Finish defining table 0N/A// Helper function for buildReduceMaps 0N/A//---------------------------generate_assertion_checks------------------- 0N/A//---------------------------addSourceBlocks----------------------------- 0N/A//---------------------------addHeaderBlocks----------------------------- 0N/A//-------------------------addPreHeaderBlocks---------------------------- 0N/A // Output #defines from definition block 0N/A//---------------------------buildReduceMaps----------------------------- 0N/A// Build mapping from enumeration for densely packed operands 0N/A// TO result and child types. 0N/A // The emit bodies currently require functions defined in the source block. 0N/A // Build external declarations for mappings 0N/A // Construct Save-Policy array 0N/A fprintf(
fp_cpp,
"// Map from machine-independent register number to register_save_policy\n");
0N/A // Construct Native Save-Policy array 0N/A fprintf(
fp_cpp,
"// Map from machine-independent register number to c_reg_save_policy\n");
0N/A // Construct Register Save Type array 0N/A fprintf(
fp_cpp,
"// Map from machine-independent register number to register_save_type\n");
0N/A // Construct the table for reduceOp 0N/A // Construct the table for leftOp 0N/A // Construct the table for rightOp 0N/A // Construct the table of rule names 0N/A // Construct the boolean table for subsumed operands 0N/A // // // Preserve in case we decide to use this table instead of another 0N/A //// Construct the boolean table for instruction chain rules 0N/A //OutputInstChainRule output_inst_chain(fp_hpp, fp_cpp, _globalNames, *this); 0N/A //build_map(output_inst_chain); 0N/A//---------------------------buildMachOperGenerator--------------------------- 0N/A// Recurse through match tree, building path through corresponding state tree, 0N/A// Until we reach the constant we are looking for. 0N/A // Base Case: access constant in ideal node linked to current state node 0N/A // Each type of constant has its own access function 0N/A // !!!!! - Update if adding a machine-independent constant type 0N/A assert(
false,
"Unsupported constant type, pointer or indefinite");
0N/A // If constant is in left child, build path and recurse 0N/A // If constant is in right child, build path and recurse 0N/A// Generate code that is executed when generating a specific Machine Operand 0N/A // Generate the case statement for this opcode 0N/A // Access parameters for constructor from the stat object 0N/A // Build access to condition code value 0N/A// Build switch to invoke "new" MachNode or MachOper 0N/A // Build switch to invoke 'new' for a specific MachOper 0N/A "//------------------------- MachOper Generator ---------------\n");
0N/A "// A switch statement on the dense-packed user-defined type system\n" 0N/A "// that invokes 'new' on the corresponding class constructor.\n");
0N/A // Place all user-defined operands into the mapping 0N/A // Ensure this is a machine-world instruction 0N/A // Do not iterate over operand classes for the operand generator!!! 0N/A // Place all internal operands into the mapping 0N/A // Generate the case statement for this opcode 0N/A // Generate the default case for switch(opcode) 0N/A fprintf(
fp_cpp,
" fprintf(stderr, \"Default MachOper Generator invoked for: \\n\");\n");
0N/A // Generate the closing for method Matcher::MachOperGenerator 0N/A//---------------------------buildMachNode------------------------------------- 0N/A// Build a new MachNode, for MachNodeGenerator or cisc-spilling 0N/A // Create the MachNode object 0N/A // Instruction that contains operands which are not in match rule. 0N/A // Check if the first post-match component may be an interesting def 0N/A // Insert operands that are not in match-rule. 0N/A // Only insert a DEF if the do_care flag is set 0N/A // Check if we don't care about DEFs or KILLs that are not USEs 0N/A // For each operand not in the match rule, call MachOperGenerator 2126N/A // with the enum for the opcode that needs to be built. 0N/A // An instruction that chains from a constant! 0N/A // In this case, we need to subsume the constant into the node 0N/A // at operand position, oper_input_base(). 0N/A // Fill in the constant 0N/A // Check for multiple constants and then fill them in. 0N/A // Just like MachOperGenerator 0N/A // Grab operand form 0N/A // Look up the number of constants 0N/A // Fill in the bottom_type where requested 0N/A//---------------------------declare_cisc_version------------------------------ 0N/A// Build CISC version of this instruction 0N/A fprintf(
fp_hpp,
" virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n");
0N/A//---------------------------define_cisc_version------------------------------- 0N/A// Build CISC version of this instruction 0N/A // Set the correct reg_mask_or_stack for the cisc operand 0N/A // Lookup the correct reg_mask_or_stack 0N/A // Construct CISC version of this instruction 0N/A // Create the MachNode object 0N/A // Fill in the bottom_type where requested 0N/A // Construct operand to access [stack_pointer + offset] 0N/A // Return result and exit scope 0N/A//---------------------------declare_short_branch_methods---------------------- 0N/A// Build prototypes for short branch methods 0N/A//---------------------------define_short_branch_methods----------------------- 0N/A// Build definitions for short branch methods 0N/A // Construct short_branch_version() method. 0N/A // Create the MachNode object 0N/A // Fill in the bottom_type where requested 0N/A // Short branch version must use same node index for access 0N/A // through allocator's tables 0N/A // Return result and exit scope 0N/A//---------------------------buildMachNodeGenerator---------------------------- 0N/A// Build switch to invoke appropriate "new" MachNode for an opcode 0N/A // Build switch to invoke 'new' for a specific MachNode 0N/A "//------------------------- MachNode Generator ---------------\n");
0N/A "// A switch statement on the dense-packed user-defined type system\n" 0N/A "// that invokes 'new' on the corresponding class constructor.\n");
0N/A // Provide constructor for all user-defined instructions 0N/A // Ensure that matrule is defined. 0N/A // Generate the case statement for this instruction 0N/A // Start local scope 0N/A // Generate code to construct the new MachNode 0N/A // Return result and exit scope 0N/A // Generate the default case for switch(opcode) 0N/A fprintf(
fp_cpp,
" fprintf(stderr, \"Default MachNode Generator invoked for: \\n\");\n");
0N/A // Generate the closing for method Matcher::MachNodeGenerator 0N/A//---------------------------buildInstructMatchCheck-------------------------- 0N/A// Output the method to Matcher which checks whether or not a specific 0N/A// instruction has a matching rule for the host architecture. 0N/A fprintf(
fp_cpp,
" assert(_last_machine_leaf < opcode && opcode < _last_opcode, \"opcode in range\");\n");
0N/A//---------------------------buildFrameMethods--------------------------------- 0N/A// Output the methods to Matcher which specify frame behavior 0N/A // Java Stack Alignment 0N/A // Java Return Address Location 0N/A // Java Stack Slot Preservation 0N/A // Top Of Stack Slot Preservation, for both Java and C 0N/A // varargs C out slots killed 0N/A // Java Argument Position 0N/A fprintf(
fp_cpp,
"void Matcher::calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length, bool is_outgoing) {\n");
0N/A // Native Argument Position 0N/A fprintf(
fp_cpp,
"void Matcher::c_calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length) {\n");
0N/A // Java Return Value Location 0N/A fprintf(
fp_cpp,
"OptoRegPair Matcher::return_value(int ideal_reg, bool is_outgoing) {\n");
0N/A // Native Return Value Location 0N/A fprintf(
fp_cpp,
"OptoRegPair Matcher::c_return_value(int ideal_reg, bool is_outgoing) {\n");
0N/A // Inline Cache Register, mask definition, and encoding 0N/A // Interpreter's Method Oop Register, mask definition, and encoding 0N/A // Interpreter's Frame Pointer Register, mask definition, and encoding 0N/A // Frame Pointer definition 0N/A /* CNC - I can not contemplate having a different frame pointer between 0N/A Java and native code; makes my head hurt to think about it. 0N/A fprintf(fp_cpp,"OptoReg::Name Matcher::frame_pointer() const {"); 0N/A fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n", 0N/A _frame->_frame_pointer); 0N/A // (Native) Frame Pointer definition 0N/A // Number of callee-save + always-save registers for calling convention 0N/A//---------------------------identify_cisc_spilling---------------------------- 0N/A// Get info for the CISC_oracle and MachNode::cisc_version() 0N/A // Find the user-defined operand for cisc-spilling 0N/A // Verify the user's suggestion 0N/A // Ensure that match field is defined. 0N/A // Successfully verified operand 0N/A // N^2 comparison of instructions looking for a cisc-spilling version 0N/A // Ensure that match field is defined. 0N/A // Grab the machine type of the operand 0N/A // Find result type for match 0N/A // Ensure that match field is defined. 0N/A//---------------------------build_cisc_spilling------------------------------- 0N/A// Get info for the CISC_oracle and MachNode::cisc_version() 0N/A // Output the table for cisc spilling 0N/A // Ensure this is a machine-world instruction 0N/A//---------------------------identify_short_branches---------------------------- 0N/A// Get info for our short branch replacement oracle. 0N/A // Walk over all instructions, checking to see if they match a short 0N/A // branching alternate. 0N/A // The instruction must have a match rule. 0N/A//---------------------------identify_unique_operands--------------------------- 0N/A// Identify unique operands. 0N/A // Walk over all instructions. 0N/A // Ensure this is a machine-world instruction