/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// output_c.cpp - Class CPP file output routines for architecture definition
#include "adlc.hpp"
// Utilities to characterize effect statements
switch(usedef) {
}
return false;
}
switch(usedef) {
}
return false;
}
switch(usedef) {
}
return false;
}
// Define an array containing the machine register names, strings.
if (registers) {
// Output the register name for each register in the allocation classes
}
// Finish defining enumeration
}
// Finish defining array
}
}
// Define an array containing the machine register encoding values
if (registers) {
// Output the register encoding for each register in the allocation classes
int encval;
} else {
// Output known constants in hex char format (backward compatibility).
}
}
// Finish defining enumeration
} // Done defining array
}
// Output an enumeration of register class names
if (registers) {
// Output an enumeration of register class names
delete[] class_name_to_upper;
}
// Finish defining enumeration
}
}
// Declare an enumeration of user-defined register classes
// and a list of register masks, one for each class.
const char *rc_name;
if (_register) {
// Build enumeration of user-defined register classes.
// Generate a list of register masks, one for each class.
fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
} else {
fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined);
}
if (reg_class->_stack_or_reg) {
fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper);
}
delete[] rc_name_to_upper;
}
}
}
// Generate an enumeration of user-defined register classes
// and a list of register masks, one for each class.
const char *rc_name;
if (_register) {
// Generate a list of register masks, one for each class.
continue;
}
{
int i;
for(i = 0; i < len - 1; i++) {
}
}
if (reg_class->_stack_or_reg) {
int i;
for(i = 0; i < len - 1; i++) {
}
}
delete[] rc_name_to_upper;
}
}
}
// Compute an index for an array in the pipeline_reads_NNN arrays
static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, PipeClassForm *pipeclass)
{
int paramcount = 0;
const char *paramname;
return -1;
if (tmppipeopnd)
else
templen += 19;
paramcount++;
}
// See if the count is zero
if (paramcount == 0) {
return -1;
}
operand_stages[0] = 0;
int i = 0;
templen = 0;
}
// See if the same string is in the table
// No, add it to the table
if (ndx < 0) {
}
else
delete [] operand_stages;
return (ndx);
}
// Compute an index for an array in the pipeline_res_stages_NNN arrays
static int pipeline_res_stages_initializer(
{
int i;
res_stages[i] = 0;
if ((1 << i) & used_mask) {
}
}
// Compute the length needed for the resource list
int commentlen = 0;
int max_stage = 0;
if (res_stages[i] == 0) {
if (max_stage < 9)
max_stage = 9;
}
else {
}
}
// Allocate space for the resource list
templen = 0;
const char * const resname =
}
// See if the same string is in the table
// No, add it to the table
if (ndx < 0) {
}
else
delete [] resource_stages;
delete [] res_stages;
return (ndx);
}
// Compute an index for an array in the pipeline_res_cycles_NNN arrays
static int pipeline_res_cycles_initializer(
{
int i;
res_cycles[i] = 0;
if ((1 << i) & used_mask) {
if (res_cycles[i] < cycles)
res_cycles[i] = cycles;
}
}
// Pre-compute the string length
int templen;
int max_cycles = 0;
if (max_cycles < res_cycles[i])
max_cycles = res_cycles[i];
}
// Allocate space for the resource list
templen = 0;
}
// See if the same string is in the table
// No, add it to the table
if (ndx < 0) {
}
else
delete [] resource_cycles;
delete [] res_cycles;
return (ndx);
}
//typedef unsigned long long uint64_t;
// Compute an index for an array in the pipeline_res_mask_NNN arrays
static int pipeline_res_mask_initializer(
{
int i, j;
int element_count = 0;
// Pre-compute the string length
int templen;
int commentlen = 0;
int max_cycles = 0;
int cycledigit = 0;
for (i = maxcycleused; i > 0; i /= 10)
cycledigit++;
int maskdigit = 0;
for (i = rescount; i > 0; i /= 10)
maskdigit++;
templen = 1 +
// Allocate space for the resource list
templen = 0;
if (!used_mask)
int formatlen =
"pipeline_res_mask_initializer: "
"semantic error: "
"pipeline stage undeclared: %s\n",
exit(1);
}
}
for (j = cyclemasksize-1; j >= 0; j--) {
}
}
resource_mask[templen] = 0;
if (last_comma)
last_comma[0] = ' ';
// See if the same string is in the table
// No, add it to the table
if (ndx < 0) {
if (strlen(resource_mask) > 0)
}
else
delete [] resource_mask;
delete [] res_mask;
//delete [] res_masks;
return (ndx);
}
const char *classname;
const char *resourcename;
int resourcenamelen = 0;
const int non_operand_latency = 0;
const int node_latency = 0;
if (!_pipeline) {
return;
}
fprintf(fp_cpp, "uint Pipeline::functional_unit_latency(uint start, const Pipeline *pred) const {\n");
#if 0
fprintf(fp_cpp, " tty->print(\"# functional_unit_latency: start == %%d, this->exclusively == 0x%%03x, pred->exclusively == 0x%%03x\\n\", start, resourcesUsedExclusively(), pred->resourcesUsedExclusively());\n");
#endif
#if 0
#endif
#if 0
fprintf(fp_cpp, " tty->print(\"# operand_latency(%%d), _read_stage_count = %%d\\n\", opnd, _read_stage_count);\n");
#endif
#if 0
fprintf(fp_cpp, " tty->print(\"# operand_latency: writeStage=%%s readStage=%%s, opnd=%%d\\n\", stageName(writeStage), stageName(readStage), opnd);\n");
#endif
#if 0
#endif
if (!_pipeline)
/* Do Nothing */;
else if (_pipeline->_maxcycleused <=
#ifdef SPARC
64
#else
32
#endif
) {
fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
}
else {
uint l;
fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
for (l = 1; l <= masklen; l++)
fprintf(fp_cpp, "Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &in1, const Pipeline_Use_Cycle_Mask &in2) {\n");
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
}
/* Get the length of all the resource names */
// Create the pipeline class description
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");
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");
fprintf(fp_cpp, "const Pipeline_Use_Element Pipeline_Use::elaborated_elements[%d] = {\n", _pipeline->_rescount);
}
fprintf(fp_cpp, "const Pipeline_Use Pipeline_Use::elaborated_use(0, 0, %d, (Pipeline_Use_Element *)&elaborated_elements[0]);\n\n",
int maxMoreInstrs = 0;
int paramcount = 0;
int i = 0;
const char *paramname;
// Scan the operands, looking for last output stage and number of inputs
if (pipeopnd) {
}
}
}
paramcount++;
}
// Create the list of stages for the operands that are read
// Note that we will build a NameList to reduce the number of copies
#if 0
// Process the Resources
const PipeClassResourceForm *piperesource;
unsigned resources_used = 0;
unsigned exclusive_resources_used = 0;
unsigned resource_groups = 0;
if (used_mask)
}
if (resource_groups > 0) {
i++ ) {
if (used_mask) {
}
}
}
#endif
// Create the pipeline class description
if (maxWriteStage < 0)
else if (maxMoreInstrs == 0)
else
if (paramcount > 0) {
}
else
else
}
// Generate the Node::latency method if _pipeline defined
if (_pipeline) {
#if 0
#endif
}
else {
}
// Output the list of nop nodes
const char *nop;
int nopcnt = 0;
int i = 0;
}
// See if the same string is in the table
fprintf(fp_cpp, " st->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n");
fprintf(fp_cpp, " st->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n");
}
// ---------------------------------------------------------------------------
//------------------------------Utilities to build Instruction Classes--------
// ---------------------------------------------------------------------------
}
if( inst_position != 0 ) {
}
}
// Scan the peepmatch and output a test for each instruction
static void check_peepmatch_instruction_sequence(FILE *fp, PeepMatch *pmatch, PeepConstraint *pconstraint) {
int inst_position = 0;
int input = 0;
// If this is not a placeholder
if( ! pmatch->is_placeholder() ) {
// Define temporaries 'inst#', based on parent and parent's input index
}
// When not the root
// Test we have the correct instruction by comparing the rule.
if( parent != -1 ) {
}
} else {
// Check that user did not try to constrain a placeholder
"fatal(): Can not constrain a placeholder instruction");
}
}
}
// Build mapping for register indices, num_edges to input
int inst_position = 0;
int input = 0;
// If this is not a placeholder
if( ! pmatch->is_placeholder() ) {
// Define temporaries 'inst#', based on self's inst_position
}
}
}
}
// Generate tests for the constraints
static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint) {
// Build mapping from num_edges to local variables
// Build constraint tests
if( pconstraint != NULL ) {
bool first_constraint = true;
while( pconstraint != NULL ) {
// indentation and connecting '&&'
// Only have '==' relation implemented
assert( false, "Unimplemented()" );
}
// LEFT
// Access info on the instructions whose operands are compared
// Access info on the operands being compared
if( left_op_index == -1 ) {
if( left_op_index == -1 ) {
}
}
// RIGHT
// Access info on the instructions whose operands are compared
// Access info on the operands being compared
if( right_op_index == -1 ) {
if( right_op_index == -1 ) {
}
}
} else { // Else match register
// assert( false, "should be a register" );
}
//
// Check for equivalence
//
// fprintf(fp, "phase->eqv( ");
// fprintf(fp, "inst%d->in(%d+%d) /* %s */, inst%d->in(%d+%d) /* %s */",
// left_index, left_op_base, left_op_index, left_op,
// right_index, right_op_base, right_op_index, right_op );
// fprintf(fp, ")");
//
switch( left_interface_type ) {
case Form::register_interface: {
// Check that they are allocated to the same register
// Need parameter for index position if not result operand
if( left_op_index != 0 ) {
// Must have index into operands
} else {
}
if( right_index != -1 ) {
if( right_op_index != 0 ) {
// Must have index into operands
} else {
}
} else {
}
break;
}
case Form::constant_interface: {
// Compare the '->constant()' values
break;
}
case Form::memory_interface: {
// Compare 'base', 'index', 'scale', and 'disp'
// base
// index
// scale
// disp
break;
}
case Form::conditional_interface: {
// Compare the condition code being tested
assert( false, "Unimplemented()" );
break;
}
default: {
assert( false, "ShouldNotReachHere()" );
break;
}
}
// Advance to next constraint
first_constraint = false;
}
}
}
// // EXPERIMENTAL -- TEMPORARY code
// static Form::DataType get_operand_type(FormDict &globals, InstructForm *instr, const char *op_name ) {
// int op_index = instr->operand_position(op_name, Component::USE);
// if( op_index == -1 ) {
// op_index = instr->operand_position(op_name, Component::DEF);
// if( op_index == -1 ) {
// op_index = instr->operand_position(op_name, Component::USE_DEF);
// }
// }
// assert( op_index != NameList::Not_in_list, "Did not find operand in instruction");
//
// ComponentList components_right = instr->_components;
// char *right_comp_type = components_right.at(op_index)->_type;
// OpClassForm *right_opclass = globals[right_comp_type]->is_opclass();
// Form::InterfaceType right_interface_type = right_opclass->interface_type(globals);
//
// return;
// }
// Construct the new sub-tree
static void generate_peepreplace( FILE *fp, FormDict &globals, PeepMatch *pmatch, PeepConstraint *pconstraint, PeepReplace *preplace, int max_position ) {
// Get the root of the new sub-tree
int inst_num;
const char *op_name;
// Then install the use-operands for the new sub-tree
// preplace->reset(); // reset breaks iteration
// find the name of the OperandForm from the local name
if( opnds_index == 0 ) {
// Initial setup of new instruction
//
// Add control edge for this node
// Add unmatched edges from root of match tree
}
// If new instruction captures bottom type
// Get bottom type from instruction whose result we are replacing
}
// Define result register and result operand
fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num);
} else {
// Do not have ideal edges for constants after matching
inst_num, inst_op_num );
} else {
}
}
++opnds_index;
}
}else {
// Replacing subtree with empty-tree
assert( false, "ShouldNotReachHere();");
}
// Return the new sub-tree
}
// Define the Peephole method for an instruction node
// Generate Peephole function header
fprintf(fp, "MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n", node->_ident);
// Identify the maximum instruction position,
// generate temporaries that hold current instruction
//
// MachNode *inst0 = NULL;
// ...
// MachNode *instMAX = NULL;
//
int max_position = 0;
}
for( int i = 0; i <= max_position; ++i ) {
if( i == 0 ) {
} else {
}
}
// For each peephole rule in architecture description
// Construct a test for the desired instruction sub-tree
// then check the constraints
// If these match, Generate the new subtree
// Root of this peephole is the current MachNode
assert( true, // %%name?%% strcmp( node->_ident, pmatch->name(0) ) == 0,
"root of PeepMatch does not match instruction");
// Make each peephole rule individually selectable
// Scan the peepmatch and output a test for each instruction
// Check constraints and build replacement inside scope
// Generate tests for the constraints
// Construct the new sub-tree
// End of scope for this peephole's constraints
// Closing brace '}' to make each peephole rule individually selectable
}
}
// Define the Expand method for an instruction node
unsigned i;
// Generate Expand function header
fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident);
// Generate expand code
const char *opid;
// If necessary, generate any operands created in expand rule
}
else {
}
}
}
cnt = 0;
// Generate the temps to use for DAG building
for(i = 0; i < numo; i++) {
}
else {
}
}
// Build mapping from num_edges to local variables
}
// Build a mapping from operand index to input edges
// The order in which the memory input is added to a node is very
// strange. Store nodes get a memory input before Expand is
// called and other nodes get it afterwards or before depending on
// match order so oper_input_base is wrong during expansion. This
// code adjusts it so that expansion will work correctly.
if (has_memory_edge) {
}
i+1,i,i);
}
// Declare variable to hold root of expansion
// Iterate over the instructions 'node' expands into
for(expand->reset_instructions();
if (expand_instruction->has_temps()) {
globalAD->syntax_err(node->_linenum, "In %s: expand rules using instructs with TEMPs aren't supported: %s",
}
// Build the node for the instruction
// Add control edge for this node
// Build the operand for the value this node defines.
// Grab the InstructForm for the new instruction
}
}
// Fill in the bottom_type where requested
}
// get the formal operand NameList
formal_lst->reset();
// Handle any memory operand
"expand rule member needs memory but top-level inst doesn't have any" );
if (has_memory_edge) {
// Copy memory edge
}
}
// Iterate over the new instruction's operands
// Use 'parameter' at current position in list of new instruction's formals
// instead of 'opid' when looking up info internal to new_inst
// Check for an operand which is created in the expand rule
// If there is no use of the created operand, just skip it
//Copy the operand from the original made above
// Check for who defines this operand & add edge if needed
}
}
else {
// Use operand name to get an index into instruction component list
// ins = (InstructForm *) _globalNames[new_id];
// For the add_req calls below to work correctly they need
// to added in the same order that a match would add them.
// This means that they would need to be in the order of
// the components list instead of the formal parameters.
// This is a sort of hidden invariant that previously
// wasn't checked and could lead to incorrectly
// constructed nodes.
syntax_err(node->_linenum, "For expand in %s to work, parameter declaration order in %s must follow matchrule\n",
}
if (new_pos != -1) {
// Copy the operand from the ExpandNode to the new node
// For each operand add appropriate input edges by looking at tmp's
// Grab corresponding edges from ExpandNode and insert them here
// This value is generated by one of the new instructions
}
}
// Update the DAG tmp's for values defined by this instruction
// If this operand is a definition in either an effects rule
// or a match rule
// Update the temp associated with this operand
}
else if( new_def_pos != -1 ) {
// Instruction defines a value but user did not declare it
// in the 'effect' clause
}
} // done iterating over a new instruction's operands
// Invoke Expand() for the newly created instruction.
} // done iterating over new instructions
} // done generating expand rule
// Generate projections for instruction's additional DEFs and KILLs
// Get string representing the MachNode that projections point at
// Generate the projections
// Examine each component to see if it is a DEF or KILL
// Skip the first component, if already handled as (SET dst (...))
// For kills, the choice of projection numbers is arbitrary
bool declared_def = false;
bool declared_kill = false;
// Lookup register class associated with operand type
if (!declared_def) {
// Define the variable "def" to hold new MachProjNodes
declared_def = true;
}
// The operand for TEMP is already constructed during
// this mach node construction, see buildMachNode().
//
// int idx = node->operand_position_format(comp->_name);
// fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n",
// idx, machOperEnum(op->_ident));
} else {
assert(false, "can't have temps which aren't registers");
}
if (!declared_kill) {
// Define the variable "kill" to hold new MachProjNodes
declared_kill = true;
}
if (!op->is_bound_register()) {
}
}
}
}
// Remove duplicated operands and inputs which use the same name.
// Seach through match operands for the same name usage.
// Build mapping from num_edges to local variables
for( i = 1; i < cur_num_opnds; i++ ) {
}
// Build a mapping from operand index to input edges
for( i = 0; i < cur_num_opnds; i++ ) {
i+1,i,i);
}
// Skip first unique operands.
for( i = 1; i < cur_num_opnds; i++ ) {
if( (int)i != node->unique_opnds_idx(i) ) {
break;
}
}
// Replace not unique operands with next unique operands.
for( ; i < cur_num_opnds; i++ ) {
int j = node->unique_opnds_idx(i);
// unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique.
if( j != node->unique_opnds_idx(j) ) {
// delete not unique edges here
}
}
// delete the rest of edges
}
}
// 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()) {
}
} else {
}
}
//------------------------------Emit Routines----------------------------------
// Special classes and routines for defining node emit routines which output
// target specific instruction object encodings.
// Define the ___Node::emit() routine
//
// (1) void ___Node::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// (2) // ... encoding defined by user
// (3)
// (4) }
//
class DefineEmitState {
private:
RELOC_IMMEDIATE = 0,
// Temporaries that describe current operand
bool _cleared;
int _operand_idx;
const char *_local_name;
const char *_operand_name;
bool _doing_disp;
bool _doing_constant;
bool _doing_emit8;
bool _doing_emit_d32;
bool _doing_emit_d16;
bool _doing_emit_hi;
bool _doing_emit_lo;
bool _may_reloc;
bool _must_reloc;
const char * _reloc_type;
bool _processing_noninput;
// Stable state, set by constructor
public:
clear();
}
void clear() {
_cleared = true;
_operand_idx = 0;
_local_name = "";
_operand_name = "";
_doing_disp = false;
_doing_constant= false;
_doing_emit8 = false;
_doing_emit_d32= false;
_doing_emit_d16= false;
_doing_emit_hi = false;
_doing_emit_lo = false;
_may_reloc = false;
_must_reloc = false;
}
// Track necessary state when identifying a replacement variable
// @arg rep_var: The formal parameter of the encoding.
// A replacement variable or one of its subfields
// Obtain replacement variable from list
if ( (*rep_var) != '$' ) {
// A replacement variable, '$' prefix
// check_rep_var( rep_var );
// No state needed.
"'primary', 'secondary' and 'tertiary' don't follow operand.");
}
if (!_inst.is_mach_constant()) {
"Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
}
}
else {
// Lookup its position in (formal) parameter list of encoding
if ( param_no == -1 ) {
"Replacement variable %s not found in enc_class %s.\n",
}
// Lookup the corresponding ins_encode parameter
// This is the argument (actual parameter) to the encoding.
if (inst_rep_var == NULL) {
"Parameter %s not passed to enc_class %s from instruct %s.\n",
}
// Check if instruction's actual parameter is a local name in the instruction
// Note: assert removed to allow constant and symbolic parameters
// assert( opc, "replacement variable was not found in local names");
// Lookup the index position iff the replacement variable is a localName
if ( idx != -1 ) {
// This is a local in the instruction
// Update local state info.
_operand_idx = idx;
// !!!!!
// Do not support consecutive operands.
}
// Instruction provided a constant expression
// Check later that encoding specifies $$$constant to resolve as constant
}
// Instruction provided an opcode: "primary", "secondary", "tertiary"
// Check later that encoding specifies $$$constant to resolve as constant
}
// Instruction provided a literal register name for this parameter
// Check that encoding specifies $$$reg to resolve.as register.
}
else {
// Check for unimplemented functionality before hard failure
assert( false, "ShouldNotReachHere()");
}
} // done checking which operand this is.
} else {
//
// A subfield variable, '$$' prefix
// Check for fields that may require relocation information.
// Then check that literal register parameters are accessed with 'reg' or 'constant'
//
_doing_disp = true;
// Only have an operand class, generate run-time check for relocation
_may_reloc = true;
} else {
// Do precise check on operand: is it a ConP or not
//
// Check interface for value of displacement
"$disp can only follow memory interface operand");
"$disp can only follow memory interface operand");
// MemInterface::disp contains a replacement variable,
// Check if this matches a ConP
//
// Lookup replacement variable, in operand's component list
// Lookup operand form for replacement variable's type
// Check if this is a constant
// Check which constant this name maps to: _c0, _c1, ..., _cn
// const int idx = _operand.constant_position(_AD.globalNames(), comp);
// assert( idx != -1, "Constant component not found in operand");
_may_reloc = true;
// No longer true that idealP is always an oop
}
}
// The only non-constant allowed access to disp is an operand sRegX in a stackSlotX
assert( op->ideal_to_sReg_type(type) != Form::none, "StackSlots access displacements using 'sRegs'");
_may_reloc = false;
} else {
assert( false, "fatal(); Only stackSlots can access a non-constant using 'disp'");
}
}
} // finished with precise check of operand for relocation.
} // finished with subfield variable
_doing_constant = true;
if ( _constant_status == LITERAL_NOT_SEEN ) {
// Check operand for type of constant
_may_reloc = true;
// No longer true that idealP is always an oop
// // _must_reloc = true;
} else {
// No relocation information needed
}
} else {
// User-provided literals may not require relocation information !!!!!
}
}
// Calls containing labels require relocation
if ( _inst.is_ideal_call() ) {
_may_reloc = true;
// !!!!! !!!!!
}
}
// literal register parameter must be accessed as a 'reg' field.
if ( _reg_status != LITERAL_NOT_SEEN ) {
} else {
assert( false, "invalid access to literal register parameter");
}
}
// literal constant parameters must be accessed as a 'constant' field
if ( _constant_status != LITERAL_NOT_SEEN ) {
} else {
assert( false, "invalid access to literal constant parameter");
}
}
}
// Handle subfield and replacement variables.
// Check for emit prefix, '$$emit32'
_doing_emit_d32 = true;
}
_doing_emit_d16 = true;
}
_doing_emit_hi = true;
}
_doing_emit_lo = true;
}
_doing_emit8 = true;
}
else {
assert( false, "fatal();");
}
}
else {
// Update state for replacement variables
update_state( rep_var );
}
_cleared = false;
}
void emit_replacement() {
// A replacement variable or one of its subfields
// Obtain replacement variable from list
// const char *ec_rep_var = encoding->_rep_vars.iter();
const char *rep_var;
if ( (*rep_var) == '$' ) {
// A subfield variable, '$$' prefix
emit_field( rep_var );
} else {
emit_rep_var( rep_var );
emit_rep_var( rep_var );
emit_rep_var( rep_var );
emit_rep_var( rep_var );
} else {
}
emit_rep_var( rep_var );
// skip trailing $Address
} else {
// A replacement variable, '$' prefix
// handle $rev_var$$base$$Register and $rev_var$$index$$Register by
// producing as_Register(opnd_array(#)->base(ra_,this,idx1)).
// emit the operand reference
emit_rep_var( rep_var );
// handle base or index
// close up the parens
} else {
emit_rep_var( rep_var );
}
}
}
}
;
}
}
void emit() {
//
// "emit_d32_reloc(" or "emit_hi_reloc" or "emit_lo_reloc"
//
// Emit the function name when generating an emit function
// In general, relocatable isn't known at compiler compile time.
// Check results of prior scan
if ( ! _may_reloc ) {
// Definitely don't need relocation information
}
else if ( _must_reloc ) {
// Must emit relocation information
}
else {
// Emit RUNTIME CHECK to see if value needs relocation info
// If emitting a relocatable address, use 'emit_d32_reloc'
&& !(_doing_disp && _doing_constant),
"Must be emitting either a displacement or a constant");
}
}
else if ( _doing_emit_d16 ) {
// Relocation of 16-bit values is not supported
// No relocation done for 16-bit values
}
else if ( _doing_emit8 ) {
// Relocation of 8-bit values is not supported
// No relocation done for 8-bit values
}
else {
// Not an emit# command, just output the replacement string.
}
// Get ready for next state collection.
clear();
}
private:
// recognizes names which represent MacroAssembler register types
// and return the conversion function to build them from OptoReg
#endif
return NULL;
}
// A subfield variable, '$$subfield'
// $reg form or the $Register MacroAssembler type conversions
"Must use this subfield after operand");
if( _reg_status == LITERAL_NOT_SEEN ) {
if (_processing_noninput) {
if (reg_convert != NULL) {
} else {
}
} else {
// Add parameter for index position, if not result operand
}
} else {
// Register literal has already been sent to output file, nothing more needed
}
}
"Must use this subfield after operand");
}
"Must use this subfield after operand");
}
}
}
if( _constant_status == LITERAL_NOT_SEEN ) {
} else {
}
} else {
// Constant literal has already been sent to output file, nothing more needed
}
}
} else {
}
}
}
}
else {
assert( false, "UnImplemented()");
}
}
_processing_noninput = false;
// A replacement variable, originally '$'
// Missing opcode
"Missing $%s opcode definition in %s, used by encoding %s\n",
}
}
}
}
}
else {
// Lookup its position in parameter list
if ( param_no == -1 ) {
"Replacement variable %s not found in enc_class %s.\n",
}
// Lookup the corresponding ins_encode parameter
// Check if instruction's actual parameter is a local name in the instruction
// Note: assert removed to allow constant and symbolic parameters
// assert( opc, "replacement variable was not found in local names");
// Lookup the index position iff the replacement variable is a localName
if( idx != -1 ) {
// This operand isn't a normal input so printing it is done
// specially.
_processing_noninput = true;
} else {
// Output the emit code for this operand
}
"Previous emit $operand does not match current");
}
// else check if it is a constant expression
// Removed following assert to allow primitive C types as arguments to encodings
// assert( _constant_status == LITERAL_ACCESSED, "Must be processing a literal constant parameter");
}
// else check if "primary", "secondary", "tertiary"
// Missing opcode
"Missing $%s opcode definition in %s\n",
}
}
// Instruction provided a literal register name for this parameter
// Check that encoding specifies $$$reg to resolve.as register.
}
else {
// Check for unimplemented functionality before hard failure
assert( false, "ShouldNotReachHere()");
}
// all done
}
}
}; // end class DefineEmitState
//(1)
// Output instruction's emit prototype
//(2)
// Print the size
// (3) and (4)
}
// defineEmit -----------------------------------------------------------------
// (1)
// Output instruction's emit prototype
// If user did not define an encode section,
// provide stub that does not generate any machine code.
return;
}
// Save current instruction's starting address (helps with relocation).
// For MachConstantNodes which are ideal jump nodes, fill the jump table.
fprintf(fp, " ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
}
// Output each operand's offset into the array of registers.
// Output this instruction's encodings
const char *ec_name;
bool user_defined = false;
// Output user-defined encoding
user_defined = true;
abort();
}
}
// Process list of user-defined strings,
// and occurrences of replacement variables.
// Replacement Vars are pushed into a list and then output
// Emit pending code
// Emit this code section
} else {
// A replacement variable or one of its subfields
// Obtain replacement variable from list
}
}
// Emit pending code
} // end while instruction's encodings
// Check if user stated which encoding to user
if ( user_defined == false ) {
}
// (3) and (4)
}
// defineEvalConstant ---------------------------------------------------------
// (1)
// Output instruction's emit prototype
// For ideal jump nodes, add a jump-table entry.
if (inst.is_ideal_jump()) {
}
// If user did not define an encode section,
// provide stub that does not generate any machine code.
return;
}
// Output this instruction's encodings
const char *ec_name;
bool user_defined = false;
// Output user-defined encoding
user_defined = true;
abort();
}
}
// Process list of user-defined strings,
// and occurrences of replacement variables.
// Replacement Vars are pushed into a list and then output
// Emit pending code
// Emit this code section
} else {
// A replacement variable or one of its subfields
// Obtain replacement variable from list
}
}
// Emit pending code
} // end while instruction's encodings
// Check if user stated which encoding to user
if (user_defined == false) {
}
// (3) and (4)
}
// ---------------------------------------------------------------------------
//--------Utilities to build MachOper and MachNode derived Classes------------
// ---------------------------------------------------------------------------
//------------------------------Utilities to build Operand Classes------------
if( num_edges != 0 ) {
// Method header
// Assert that the index is in range.
// Figure out if all RegMasks are the same.
bool all_same = true;
all_same = false;
}
}
if (all_same) {
// Return the sole RegMask.
} else {
delete[] first_reg_class_to_upper;
}
} else {
// Build a switch statement to return the desired mask.
} else {
delete[] reg_class_to_upper;
}
}
}
// Method close
}
}
// generate code to create a clone for a class derived from MachOper
//
// (0) MachOper *MachOperXOper::clone(Compile* C) const {
// (1) return new (C) MachXOper( _ccode, _c0, _c1, ..., _cn);
// (2) }
//
// Check for constants that need to be copied over
if( (num_consts > 0) ) {
// generate parameters for constants
int i = 0;
for( i = 1; i < num_consts; ++i) {
}
// finish line (1)
}
else {
}
// finish method
}
// Helper functions for bug 4796752, abstracted with minimal modification
// from define_oper_interface()
// Check for replacement variable
if( *encoding == '$' ) {
// Replacement variable
// Lookup replacement variable, rep_var, in operand's component list
// Lookup operand form for replacement variable's type
}
return op;
}
// Check for replacement variable
if( *encoding == '$' ) {
// Replacement variable
// Lookup replacement variable, rep_var, in operand's component list
// Lookup operand form for replacement variable's type
// Check that this is a constant and find constant's index:
}
}
return idx;
}
bool is_regI = false;
// Check that this is a register
// Register
}
}
return is_regI;
}
bool is_conP = false;
// Check that this is a constant pointer
// Constant
}
}
return is_conP;
}
// Define a MachOper interface methods
bool emit_position = false;
// Generate access method for base, index, scale, disp, ...
emit_position = true;
} else {
}
// Check for hexadecimal value OR replacement variable
if( *encoding == '$' ) {
// Replacement variable
// Lookup replacement variable, rep_var, in operand's component list
// Lookup operand form for replacement variable's type
// Check that this is a register or a constant and generate code:
// Register
// StackSlot for an sReg comes either from input node or from self, when idx==0
// Constant
// Check which constant this name maps to: _c0, _c1, ..., _cn
// Output code for this constant, type dependent.
} else {
assert( false, "Attempting to emit a non-register or non-constant");
}
}
// Hex value
} else {
assert( false, "Do not support octal or decimal encode constants");
}
// Found a memory access using a constant pointer for a displacement
// and a base register containing an integer offset.
// In this case the base and disp are reversed with respect to what
// is expected by MachNode::get_base_and_disp() and MachNode::adr_type().
// Provide a non-NULL return for disp_as_type() that will allow adr_type()
// to correctly compute the access type for alias analysis.
//
// See BugId 4796752, operand indOffset32X in i486.ad
}
}
}
//
// Construct the method to copy _idx, inputs and operands to new node.
if( !used ) {
} else {
// New node must use same node index for access through allocator's tables
// Copy machine-independent inputs
// Copy machine operands to new MachNode
fprintf(fp_cpp, " assert( node->num_opnds() == (uint)nopnds, \"Must have same number of operands\");\n");
}
}
//------------------------------defineClasses----------------------------------
// Define members of MachNode and MachOper classes based on
// operand and instruction lists
// Define the contents of an array containing the machine register names
// Define an array containing the machine register encoding values
// Generate an enumeration of user-defined register classes
// and a list of register masks, one for each class.
// Only define the RegMask value objects in the expand file.
// Declare each as an extern const RegMask ...; in ad_<arch>.hpp
// build_register_masks(fp);
// Define the pipe_classes
// Generate Machine Classes for each operand defined in AD file
// Iterate through all operands
// Ensure this is a machine-world instruction
if ( oper->ideal_only() ) continue;
// !!!!!
// The declaration of labelOper is in machine-independent file: machnode
// // Currently all XXXOper::Hash() methods are identical (990820)
// define_hash(fp, oper->_ident);
// // Currently all XXXOper::Cmp() methods are identical (990820)
// define_cmp(fp, oper->_ident);
continue;
}
// The declaration of methodOper is in machine-independent file: machnode
// // Currently all XXXOper::Hash() methods are identical (990820)
// define_hash(fp, oper->_ident);
// // Currently all XXXOper::Cmp() methods are identical (990820)
// define_cmp(fp, oper->_ident);
continue;
}
// // Currently all XXXOper::Hash() methods are identical (990820)
// define_hash(fp, oper->_ident);
// // Currently all XXXOper::Cmp() methods are identical (990820)
// define_cmp(fp, oper->_ident);
// side-call to generate output that used to be in the header file:
}
// Generate Machine Classes for each instruction defined in AD file
// Output the definitions for out_RegMask() // & kill_RegMask()
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
}
bool used = false;
// Output the definitions for expand rules & peephole rules
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
instr->is_mach_constant() ||
// If there is an explicit peephole rule, build it
// Output code to convert to the cisc version, if applicable
// Output code to convert to the short branch version, if applicable
}
// Construct the method called by cisc_version() to copy inputs and operands.
// Output the definitions for labels
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
// Access the fields for operand Label
if( label_position != -1 ) {
// Set the label
// Save the label
}
}
// Output the definitions for methods
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
// Access the fields for operand Label
if( method_position != -1 ) {
// Access the method's address
}
}
// Define this instruction's number of relocation entries, base is '0'
// Output the definition for number of relocation entries
if ( reloc_size != 0 ) {
}
}
// Output the definitions for code generation
//
// address ___Node::emit(address ptr, PhaseRegAlloc *ra_) const {
// // ... encoding defined by user
// return ptr;
// }
//
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
// side-call to generate output that used to be in the header file:
}
// Output the definitions for alias analysis
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
// Analyze machine instructions that either USE or DEF memory.
// Some guys kill all of memory
}
fprintf(fp,"const MachOper* %sNode::memory_operand() const { return (MachOper*)-1; }\n", instr->_ident);
} else {
fprintf(fp,"const MachOper* %sNode::memory_operand() const { return _opnds[%d]; }\n", instr->_ident, memory_operand);
}
}
}
// Get the length of the longest identifier
int max_ident_len = 0;
if( max_ident_len < ident_len )
}
}
// Emit specifically for Node(s)
fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*s::pipeline() const { return pipeline_class(); }\n",
max_ident_len, "MachNode");
// Output the definitions for machine node specific pipeline data
_machnodes.reset();
fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %sNode::pipeline() const { return (&pipeline_class_%03d); }\n",
}
// Output the definitions for instruction pipeline static data references
fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline_class() { return (&pipeline_class_%03d); }\n",
max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num);
fprintf(_CPP_PIPELINE_file._fp, "const Pipeline * %*sNode::pipeline() const { return (&pipeline_class_%03d); }\n",
max_ident_len, instr->_ident, ((class PipeClassForm *)_pipeline->_classdict[instr->_ins_pipe])->_num);
}
}
}
// -------------------------------- maps ------------------------------------
// Information needed to generate the ReduceOp mapping for the DFA
public:
}
}
// Most operands without match rules, e.g. eFlagsReg, do not have a result operand
// operand stackSlot does not have a match rule, but produces a stackSlot
}
}
}
};
// Information needed to generate the LeftOp mapping for the DFA
public:
}
}
}
}
};
// Information needed to generate the RightOp mapping for the DFA
public:
}
}
}
}
};
// Information needed to generate the Rule names for the DFA
public:
}
};
// Information needed to generate the swallowed mapping for the DFA
public:
}
}
};
// Information needed to generate the decision array for instruction chain rule
public:
}
}
};
//---------------------------build_map------------------------------------
// Build mapping from enumeration for densely packed operands
// TO result and child types.
int idx = 0;
// Construct this mapping
map.declaration();
map.definition();
// Output the mapping for operands
// Ensure this is a machine-world instruction
if ( op->ideal_only() ) continue;
// Generate the entry for this opcode
++idx;
};
// Place all user-defined operand classes into the mapping
++idx;
};
// Place all internally defined operands into the mapping
++idx;
};
// Place all user-defined instructions into the mapping
if( map.do_instructions() ) {
// Output all simple instruction chain rules first
{
// Ensure this is a machine-world instruction
if ( inst->ideal_only() ) continue;
++idx;
};
// Ensure this is a machine-world instruction
if ( inst->ideal_only() ) continue;
++idx;
};
}
// Output all instructions that are NOT simple chain rules
{
// Ensure this is a machine-world instruction
if ( inst->ideal_only() ) continue;
++idx;
};
// Ensure this is a machine-world instruction
if ( inst->ideal_only() ) continue;
++idx;
};
}
}
// Finish defining table
};
// Helper function for buildReduceMaps
char callconv;
else callconv = 'Z';
return callconv;
}
//---------------------------generate_assertion_checks-------------------
}
//---------------------------addSourceBlocks-----------------------------
}
//---------------------------addHeaderBlocks-----------------------------
}
//-------------------------addPreHeaderBlocks----------------------------
// Output #defines from definition block
if (_pre_header.count() > 0)
}
//---------------------------buildReduceMaps-----------------------------
// Build mapping from enumeration for densely packed operands
// TO result and child types.
// The emit bodies currently require functions defined in the source block.
// Build external declarations for mappings
// Construct Save-Policy array
}
// Construct Native Save-Policy array
}
// Construct Register Save Type array
}
// Construct the table for reduceOp
// Construct the table for leftOp
// Construct the table for rightOp
// Construct the table of rule names
// Construct the boolean table for subsumed operands
// // // Preserve in case we decide to use this table instead of another
//// Construct the boolean table for instruction chain rules
//OutputInstChainRule output_inst_chain(fp_hpp, fp_cpp, _globalNames, *this);
//build_map(output_inst_chain);
}
//---------------------------buildMachOperGenerator---------------------------
// Recurse through match tree, building path through corresponding state tree,
// Until we reach the constant we are looking for.
if ( ! mnode) return;
unsigned position = 0;
// Base Case: access constant in ideal node linked to current state node
// Each type of constant has its own access function
// !!!!! - Update if adding a machine-independent constant type
assert( false, "Unsupported constant type, pointer or indefinite");
} else {
assert( false, "Unsupported constant type");
}
return;
}
// If constant is in left child, build path and recurse
return;
}
// If constant is in right child, build path and recurse
return;
}
assert( false, "ShouldNotReachHere()");
}
// Generate code that is executed when generating a specific Machine Operand
OperandForm &op) {
// Generate the case statement for this opcode
// Access parameters for constructor from the stat object
//
// Build access to condition code value
if ( (num_consts > 0) ) {
uint i = 0;
for ( i = 1; i < num_consts; ++i ) {
}
}
}
// Build switch to invoke "new" MachNode or MachOper
int idx = 0;
// Build switch to invoke 'new' for a specific MachOper
"//------------------------- MachOper Generator ---------------\n");
"// A switch statement on the dense-packed user-defined type system\n"
"// that invokes 'new' on the corresponding class constructor.\n");
// Place all user-defined operands into the mapping
int opIndex = 0;
// Ensure this is a machine-world instruction
if ( op->ideal_only() ) continue;
};
// Do not iterate over operand classes for the operand generator!!!
// Place all internal operands into the mapping
const char *iopn;
// Generate the case statement for this opcode
};
// Generate the default case for switch(opcode)
// Generate the closing for method Matcher::MachOperGenerator
}
//---------------------------buildMachNode-------------------------------------
// Build a new MachNode, for MachNodeGenerator or cisc-spilling
// Create the MachNode object
if ( (inst->num_post_match_opnds() != 0) ) {
// Instruction that contains operands which are not in match rule.
//
// Check if the first post-match component may be an interesting def
bool dont_care = false;
// Insert operands that are not in match-rule.
// Only insert a DEF if the do_care flag is set
// Check if we don't care about DEFs or KILLs that are not USEs
continue;
}
dont_care = true;
// For each operand not in the match rule, call MachOperGenerator
// with the enum for the opcode that needs to be built.
}
}
// An instruction that chains from a constant!
// In this case, we need to subsume the constant into the node
// at operand position, oper_input_base().
//
// Fill in the constant
// #####
// Check for multiple constants and then fill them in.
// Just like MachOperGenerator
// Grab operand form
// Look up the number of constants
if ( (num_consts > 0) ) {
uint i = 0;
for ( i = 1; i < num_consts; ++i ) {
}
}
// #####
}
// Fill in the bottom_type where requested
}
if( inst->is_ideal_if() ) {
}
if( inst->is_ideal_fastlock() ) {
}
}
//---------------------------declare_cisc_version------------------------------
// Build CISC version of this instruction
if( AD.can_cisc_spill() ) {
}
}
}
//---------------------------define_cisc_version-------------------------------
// Build CISC version of this instruction
//
// Set the correct reg_mask_or_stack for the cisc operand
// Lookup the correct reg_mask_or_stack
//
// Construct CISC version of this instruction
// Create the MachNode object
// Fill in the bottom_type where requested
}
}
// Construct operand to access [stack_pointer + offset]
fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new (C) %sOper(offset));\n", cisc_oper_name);
// Return result and exit scope
return true;
}
return false;
}
//---------------------------declare_short_branch_methods----------------------
// Build prototypes for short branch methods
if (has_short_branch_form()) {
}
}
//---------------------------define_short_branch_methods-----------------------
// Build definitions for short branch methods
if (has_short_branch_form()) {
// Construct short_branch_version() method.
// Create the MachNode object
if( is_ideal_if() ) {
}
// Fill in the bottom_type where requested
}
// Short branch version must use same node index for access
// through allocator's tables
// Return result and exit scope
return true;
}
return false;
}
//---------------------------buildMachNodeGenerator----------------------------
// Build switch to invoke appropriate "new" MachNode for an opcode
// Build switch to invoke 'new' for a specific MachNode
"//------------------------- MachNode Generator ---------------\n");
"// A switch statement on the dense-packed user-defined type system\n"
"// that invokes 'new' on the corresponding class constructor.\n");
// Provide constructor for all user-defined instructions
// Ensure that matrule is defined.
// Generate the case statement for this instruction
// Start local scope
// Generate code to construct the new MachNode
// Return result and exit scope
}
// Generate the default case for switch(opcode)
// Generate the closing for method Matcher::MachNodeGenerator
}
//---------------------------buildInstructMatchCheck--------------------------
// Output the method to Matcher which checks whether or not a specific
// instruction has a matching rule for the host architecture.
fprintf(fp_cpp, " assert(_last_machine_leaf < opcode && opcode < _last_opcode, \"opcode in range\");\n");
int i;
for (i = 0; i < _last_opcode - 1; i++) {
NodeClassNames[i]);
}
NodeClassNames[i]);
}
//---------------------------buildFrameMethods---------------------------------
// Output the methods to Matcher which specify frame behavior
// Stack Direction
// Sync Stack Slots
// Java Stack Alignment
_frame->_alignment);
// Java Return Address Location
if (_frame->_return_addr_loc) {
}
else {
}
// Java Stack Slot Preservation
// Top Of Stack Slot Preservation, for both Java and C
// varargs C out slots killed
// Java Argument Position
fprintf(fp_cpp,"void Matcher::calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length, bool is_outgoing) {\n");
// Native Argument Position
fprintf(fp_cpp,"void Matcher::c_calling_convention(BasicType *sig_bt, VMRegPair *regs, uint length) {\n");
// Java Return Value Location
// Native Return Value Location
// Inline Cache Register, mask definition, and encoding
// Interpreter's Method Oop Register, mask definition, and encoding
// Interpreter's Frame Pointer Register, mask definition, and encoding
else
// Frame Pointer definition
/* CNC - I can not contemplate having a different frame pointer between
Java and native code; makes my head hurt to think about it.
fprintf(fp_cpp,"OptoReg::Name Matcher::frame_pointer() const {");
fprintf(fp_cpp," return OptoReg::Name(%s_num); }\n\n",
_frame->_frame_pointer);
*/
// (Native) Frame Pointer definition
// Number of callee-save + always-save registers for calling convention
int nof_saved_registers = 0;
}
}
static int PrintAdlcCisc = 0;
//---------------------------identify_cisc_spilling----------------------------
// Get info for the CISC_oracle and MachNode::cisc_version()
return;
// Find the user-defined operand for cisc-spilling
// Verify the user's suggestion
// Ensure that match field is defined.
// Successfully verified operand
if( _cisc_spill_debug ) {
}
}
}
}
}
}
}
if( cisc_spill_operand() != NULL ) {
// N^2 comparison of instructions looking for a cisc-spilling version
// Ensure that match field is defined.
// Grab the machine type of the operand
// Find result type for match
bool found_cisc_alternate = false;
// Ensure that match field is defined.
}
}
}
}
}
//---------------------------build_cisc_spilling-------------------------------
// Get info for the CISC_oracle and MachNode::cisc_version()
// Output the table for cisc spilling
// Ensure this is a machine-world instruction
if ( inst->ideal_only() ) continue;
}
}
}
//---------------------------identify_short_branches----------------------------
// Get info for our short branch replacement oracle.
// Walk over all instructions, checking to see if they match a short
// branching alternate.
// The instruction must have a match rule.
instr->is_short_branch()) {
}
}
}
}
//---------------------------identify_unique_operands---------------------------
// Identify unique operands.
// Walk over all instructions.
// Ensure this is a machine-world instruction
if (!instr->ideal_only()) {
}
}
}