/*
* 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_h.cpp - Class HPP file output routines for architecture definition
#include "adlc.hpp"
// The comment delimiter used in format statements after assembler instructions.
// Generate the #define that describes the number of registers.
if (registers) {
}
}
// Output enumeration of machine register numbers
// (1)
// // Enumerate machine registers starting after reserved regs.
// // in the order of occurrence in the register block.
// enum MachRegisterNumbers {
// EAX_num = 0,
// ...
// _last_Mach_Reg
// }
if (_register) {
// Output a #define for the number of machine registers
// Count all the Save_On_Entry and Always_Save registers
int saved_on_entry = 0;
int c_saved_on_entry = 0;
}
// (1)
// Build definition for enumeration of register numbers
// Output the register number for each register in the allocation classes
int i = 0;
i++,
reg_def->register_num(),
reg_def->register_encode());
}
// Finish defining enumeration
}
for( int i = 0; i < len; i++ )
// All RegMasks are declared "extern const ..." in ad_<arch>.hpp
// fprintf(fp_hpp,"extern RegMask STACK_OR_STACK_SLOTS_mask;\n\n");
}
// Output enumeration of machine register encodings
// (2)
// // Enumerate machine registers starting after reserved regs.
// // in the order of occurrence in the alloc_class(es).
// enum MachRegisterEncodes {
// EAX_enc = 0x00,
// ...
// }
if (_register) {
// (2)
// Build definition for enumeration of encode values
// Find max enum string length.
}
// Output the register encoding for each register in the allocation classes
}
// Finish defining enumeration
} // Done with register form
}
// Declare an array containing the machine register names, strings.
if (registers) {
// fprintf(fp,"\n");
// fprintf(fp,"// An array of character pointers to machine register names.\n");
// fprintf(fp,"extern const char *regName[];\n");
}
}
// Declare an array containing the machine register sizes in 32-bit words.
// regSize[] is not used
}
// Declare an array containing the machine register encoding values
if (registers) {
// // //
// fprintf(fp,"\n");
// fprintf(fp,"// An array containing the machine register encode values\n");
// fprintf(fp,"extern const char regEncode[];\n");
}
}
// ---------------------------------------------------------------------------
//------------------------------Utilities to build Instruction Classes--------
// ---------------------------------------------------------------------------
}
// ---------------------------------------------------------------------------
//--------Utilities to build MachOper and MachNode derived Classes------------
// ---------------------------------------------------------------------------
//------------------------------Utilities to build Operand Classes------------
}
int i = 0;
// Iterate over the component list looking for constants
}
}
}
}
}
}
}
else {
assert(0, "Non-constant operand lacks component list.");
}
} // end if NULL
else {
i++;
}
i++;
}
i++;
}
i++;
}
i++;
}
i++;
}
}
}
}
// Declare constructor.
// Parameters start with condition code, then all other constants
//
// (0) public:
// (1) MachXOper(int32 ccode, int32 c0, int32 c1, ..., int32 cn)
// (2) : _ccode(ccode), _c0(c0), _c1(c1), ..., _cn(cn) { }
//
// generate line (1)
if( num_consts == 0 ) {
return;
}
// generate parameters for constants
uint i = 0;
switch( constant_type ) {
break;
}
default:
break;
}
} // end if NULL
else {
i++;
}
i++;
}
i++;
}
i++;
}
i++;
}
i++;
}
i++;
}
}
}
// finish line (1) and start line (2)
// generate initializers for constants
i = 0;
for( i = 1; i < num_consts; ++i) {
}
// The body for the constructor is empty
}
// ---------------------------------------------------------------------------
// Utilities to generate format rules for machine operands and instructions
// ---------------------------------------------------------------------------
// Generate the format rule for condition codes
}
// Output code that dumps constant values, increment "i" if type is constant
++i;
}
++i;
}
++i;
}
++i;
}
++i;
}
++i;
}
++i;
}
return i;
}
// Generate the format rule for an operand
if (!for_c_file) {
// invoked after output #ifndef PRODUCT to ad_<arch>.hpp
// compile the bodies separately, to cut down on recompilations
fprintf(fp," virtual void int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const;\n");
fprintf(fp," virtual void ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const;\n");
return;
}
// Local pointer indicates remaining part of format rule
// Generate internal format function, used when stored locally
fprintf(fp,"void %sOper::int_format(PhaseRegAlloc *ra, const MachNode *node, outputStream *st) const {\n", oper._ident);
// Generate the user-defined portion of the format
// No initialization code for int_format
// Build the format from the entries in strings and rep_vars
// Check if this is a standard string or a replacement variable
// Normal string
// Pass through to st->print
} else {
// Replacement variable
// Check that it is a local name, and an operand
}
// Get index if register or constant
}
} else {
idx = 0;
}
// output invocation of "$..."s format function
if ( idx == -1 ) {
"Using a name, %s, that isn't in match rule\n", rep_var);
}
} // Done with a replacement variable
} // Done with all format strings
} else {
// Default formats for base operands (RegI, RegP, ConI, ConP, ...)
}
} else { // oper._format == NULL
// Provide a few special case formats where the AD writer cannot.
}
// labelOper::int_format is defined in ad_<...>.cpp
}
// ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) {
}
// Generate external format function, when data is stored externally
fprintf(fp,"void %sOper::ext_format(PhaseRegAlloc *ra, const MachNode *node, int idx, outputStream *st) const {\n", oper._ident);
// Generate the user-defined portion of the format
// Check for a replacement string "$..."
// Initialization code for ext_format
}
// Build the format from the entries in strings and rep_vars
// Check if this is a standard string or a replacement variable
// Normal string
// Pass through to st->print
} else {
// Replacement variable
// Check that it is a local name, and an operand
}
// Get index if register or constant
}
} else {
idx = 0;
}
// output invocation of "$..."s format function
// Lookup the index position of the replacement variable
if ( idx == -1 ) {
"Using a name, %s, that isn't in match rule\n", rep_var);
}
} // Done with a replacement variable
} // Done with all format strings
} else {
// Default formats for base operands (RegI, RegP, ConI, ConP, ...)
}
} else { // oper._format == NULL
// Provide a few special case formats where the AD writer cannot.
}
// labelOper::ext_format is defined in ad_<...>.cpp
}
// ALWAYS! Provide a special case output for condition codes.
if( oper.is_ideal_bool() ) {
}
}
// Generate the format rule for an instruction
if (!for_c_file) {
// compile the bodies separately, to cut down on recompilations
// #ifndef PRODUCT region generated by caller
return;
}
// Define the format function
// Generate the user-defined portion of the format
// If there are replacement variables,
// Generate index values needed for determining the operand position
// Build the format from the entries in strings and rep_vars
// Check if this is a standard string or a replacement variable
assert(false, "ShouldNotReachHere()");
}
// Lookup the index position of the replacement variable
if ( idx == -1 ) {
assert( false, "ShouldNotReachHere()");
}
assert( false, "ShouldNotReachHere()");
} else {
// Output the format call for this operand
}
} else {
}
} else {
assert( false, "ShouldNotReachHere()");
}
else
} // Done with all format strings
} // Done generating the user-defined portion of the format
// Add call debug info automatically
switch( call_type ) {
case Form::JAVA_DYNAMIC:
break;
case Form::JAVA_STATIC:
break;
case Form::JAVA_COMPILED:
case Form::JAVA_INTERP:
break;
case Form::JAVA_RUNTIME:
case Form::JAVA_NATIVE:
break;
default:
assert(0,"ShouldNotReachHere");
}
fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" );
}
else if(inst.is_ideal_safepoint()) {
fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" );
}
else if( inst.is_ideal_if() ) {
}
else if( inst.is_ideal_mem() ) {
// Print out the field name if available to improve readability
// Make sure 'Volatile' gets printed out
}
// Complete the definition of the format function
}
if (!_pipeline)
return;
if (_pipeline->_maxcycleused <=
#ifdef SPARC
64
#else
32
#endif
) {
else {
fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint mask1, uint mask2) : _mask((((uint64_t)mask1) << 32) | mask2) {}\n\n");
}
fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n");
fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n");
}
else {
uint l;
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = 1; l <= masklen; l++)
for (l = masklen; l > 1; l--)
for (l = 2; l < masklen; l++) {
fprintf(fp_hpp, " uint temp%d = mask & (_mask%d >> m); _mask%d <<= n; _mask%d |= temp%d;\n", l+1, l, l, l, l);
}
fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator&(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n");
fprintf(fp_hpp, " friend Pipeline_Use_Cycle_Mask operator|(const Pipeline_Use_Cycle_Mask &, const Pipeline_Use_Cycle_Mask &);\n\n");
}
const char *resource;
rescount++;
}
fprintf(fp_hpp, " Pipeline_Use_Element(uint used, uint lb, uint ub, bool multiple, Pipeline_Use_Cycle_Mask mask)\n");
fprintf(fp_hpp, " Pipeline_Use(uint resources_used, uint resources_used_exclusively, uint count, Pipeline_Use_Element *elements)\n");
fprintf(fp_hpp, " uint resourcesUsedExclusively() const { return _resources_used_exclusively; }\n\n");
rescount);
rescount);
"unspecified pipeline architecture units");
if( _pipeline->_bundleUnitSize != 0 )
if( _pipeline->_instrUnitSize != 0 )
else
else
if( _pipeline->_instrUnitSize != 0 )
else
if( _pipeline->_instrUnitSize == 0 )
if( _pipeline->_bundleUnitSize != 0 )
else
if( _pipeline->_bundleUnitSize == 0 )
for (uint msize = _pipeline->_maxInstrsPerBundle * _pipeline->_maxBundlesPerCycle; msize != 0; msize >>= 1)
mshift++;
fprintf(fp_hpp, " Bundle() : _flags(_unused_delay), _starts_bundle(0), _instr_count(0), _resources_used(0) {}\n\n");
fprintf(fp_hpp, " void set_used_in_unconditional_delay() { _flags = _used_in_unconditional_delay; }\n");
fprintf(fp_hpp, " void set_used_in_conditional_delay() { _flags = _used_in_conditional_delay; }\n");
fprintf(fp_hpp, " void set_used_in_all_conditional_delays() { _flags = _used_in_all_conditional_delays; }\n");
fprintf(fp_hpp, " bool use_unconditional_delay() { return (_flags == _use_unconditional_delay); }\n");
fprintf(fp_hpp, " bool used_in_unconditional_delay() { return (_flags == _used_in_unconditional_delay); }\n");
fprintf(fp_hpp, " bool used_in_conditional_delay() { return (_flags == _used_in_conditional_delay); }\n");
fprintf(fp_hpp, " bool used_in_all_conditional_delays() { return (_flags == _used_in_all_conditional_delays); }\n");
// const char *classname;
// for (_pipeline->_classlist.reset(); (classname = _pipeline->_classlist.iter()) != NULL; ) {
// PipeClassForm *pipeclass = _pipeline->_classdict[classname]->is_pipeclass();
// fprintf(fp_hpp, "// Pipeline Class Instance for \"%s\"\n", classname);
// }
}
//------------------------------declareClasses---------------------------------
// Construct the class hierarchy of MachNode classes from the instruction &
// operand lists
// Declare an array containing the machine register names, strings.
// Declare an array containing the machine register encoding values
// Generate declarations for the total number of operands
int num_operands = 0;
// Ensure this is a machine-world instruction
if (op->ideal_only()) continue;
++num_operands;
}
// Ensure this is a machine-world instruction
if (opc->ideal_only()) continue;
++num_operands;
}
// Generate declarations for the total number of instructions
// 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
// The declaration of methodOper is in machine-independent file: machnode
// Build class definition for this operand
// Operand definitions that depend upon number of input edges
{
num_edges );
}
if( num_edges > 0 ) {
in_RegMask(fp);
}
}
// Support storing constants inside the MachOper
// Support storage of the condition codes
if( oper->is_ideal_bool() ) {
}
// Support storage of the condition codes
if( oper->is_ideal_bool() ) {
}
// Declare constructor.
// Parameters start with condition code, then all other constants
//
// (1) MachXOper(int32 ccode, int32 c0, int32 c1, ..., int32 cn)
// (2) : _ccode(ccode), _c0(c0), _c1(c1), ..., _cn(cn) { }
//
// Clone function
// Support setting a spill offset into a constant operand.
// We only support setting an 'int' offset, while in the
// LP64 build spill offsets are added with an AddP which
// requires a long constant. Thus we don't support spilling
// in frames larger than 4Gig.
// virtual functions for encoding and format
// fprintf(fp," virtual void encode() const {\n %s }\n",
// (oper->_encrule)?(oper->_encrule->_encrule):"");
// Check the interface type, and generate the correct query functions
// encoding queries based upon MEMORY_INTER, REG_INTER, CONST_INTER.
// virtual function to look up ideal return type of machine instruction
//
// (1) virtual const Type *type() const { return .....; }
//
unsigned int position = 0;
// Check if we are an ideal pointer type
// Return the ideal type we already have: <TypePtr *>
} else {
// Return the appropriate bottom type
}
} else {
}
} else {
// Check for user-defined stack slots, based upon sRegX
switch( data_type ) {
default:
assert( false, "No support for this type of stackSlot");
}
}
}
//
// virtual functions for defining the encoding interface.
//
// Access the linearized ideal register mask,
// map to physical register encoding
// Just use the default virtual 'reg' call
// Special handling for operand 'sReg', a Stack Slot Register.
// Map linearized ideal register mask to stack slot number
}
// Output the operand specific access functions used by an enc_class
// These are only defined when we want to override the default virtual func
// Check if it is a Memory Interface
}
}
}
}
// should not call this:
}
} // end Memory Interface
// Check if it is a Conditional Interface
}
}
}
if( greater_equal != NULL ) {
}
if( less_equal != NULL ) {
}
}
} // end Conditional Interface
// Check if it is a Constant Interface
"Must have one constant when using CONST_INTER encoding");
// Access the locally stored constant
}
// Access the locally stored constant
// Generate query to determine if this pointer is an oop
}
// Access the locally stored constant
// Generate query to determine if this pointer is an oop
}
// We don't support addressing modes with > 4Gig offsets.
// Truncate to int.
}
}
}
}
// make sure that a fixed format string isn't used for an
// operand which might be assiged to multiple registers.
// Otherwise the opto assembly output could be misleading.
"Only bound registers can have fixed formats: %s\n",
}
}
else {
assert( false, "ShouldNotReachHere();");
}
}
// // Currently all XXXOper::hash() methods are identical (990820)
// declare_hash(fp);
// // Currently all XXXOper::Cmp() methods are identical (990820)
// declare_cmp(fp);
// Do not place dump_spec() and Name() into PRODUCT code
// int_format and ext_format are not needed in PRODUCT code either
// Declare int_format() and ext_format()
// Machine independent print functionality for debugging
// IF we have constants, create a dump_spec function for the derived class
//
// (1) virtual void dump_spec() const {
// (2) st->print("#%d", _c#); // Constant != ConP
// OR _c#->dump_on(st); // Type ConP
// ...
// (3) }
if( num_consts > 0 ) {
// line (1)
// generate format string for st->print
// Iterate over the component list & spit out the right thing
uint i = 0;
// Check that type actually matched
assert( i != 0, "Non-constant operand lacks component list.");
} // end if NULL
else {
// line (2)
// dump all components
}
}
// finish line (3)
}
// Close definition of this XxxMachOper
}
// Generate Machine Classes for each instruction defined in AD file
// Generate Machine Classes for each instruction defined in AD file
// Ensure this is a machine-world instruction
if ( instr->ideal_only() ) continue;
// Build class definition for this instruction
if ( instr->is_ideal_jump() ) {
}
if ( instr->is_ideal_jump() ) {
}
}
// If this instruction contains a labelOper
// Declare Node::methods that set operand Label's contents
if( label_position != -1 ) {
}
// If this instruction contains a methodOper
// Declare Node::methods that set operand method's contents
if( method_position != -1 ) {
// Set the address method, stored in methodOper::_method
}
// virtual functions for attributes
//
// Each instruction attribute results in a virtual call of same name.
// The ins_cost is not handled here.
bool avoid_back_to_back = false;
}
// Check value for ins_avoid_back_to_back, and if it is true (1), set the flag
avoid_back_to_back = true;
}
// virtual functions for encode and format
// Virtual function for evaluating the constant.
if (instr->is_mach_constant()) {
}
// Output the opcode function and the encode function here using the
// encoding class information in the _insencode slot.
if ( instr->_insencode ) {
}
// virtual function for getting the size of an instruction
}
// Return the top-level ideal opcode.
// Use MachNode::ideal_Opcode() for nodes based on MachNode class
// if the ideal_Opcode == Op_Node.
}
// Allow machine-independent optimization, invert the sense of the IF test
if( instr->is_ideal_if() ) {
// Identify which operand contains the negate(able) ideal condition code
int idx = 0;
// Check that component is an operand
// Lookup the position of the operand in the instruction.
if( opForm->is_ideal_bool() ) {
break;
}
}
}
// Identify which input register matches the input register.
// Generate the method if it returns != 0 otherwise use MachNode::two_adr()
if( matching_input != 0 ) {
}
// Declare cisc_version, if applicable
// MachNode *cisc_version( int offset /* ,... */ );
// If there is an explicit peephole rule, build it
fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n");
}
// Output the declaration for number of relocation entries
}
}
// Starting point for inputs matcher wants.
// Use MachNode::oper_input_base() for nodes based on MachNode class
// if the base == 1.
}
// Make the constructor and following methods 'public:'
// Constructor
if ( instr->is_ideal_jump() ) {
} else {
}
}
bool node_flags_set = false;
// flag: if this instruction matches an ideal 'Copy*' node
if ( instr->is_ideal_copy() != 0 ) {
node_flags_set = true;
}
// Is an instruction is a constant? If so, get its type
// Check if this instruction is a constant
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
// flag: if this instruction is cisc alternate
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
// flag: if this instruction has short branch form
if ( instr->has_short_branch_form() ) {
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
// flag: if this instruction should not be generated back to back.
if ( avoid_back_to_back ) {
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
// Check if machine instructions that USE memory, but do not DEF memory,
// depend upon a node that defines memory in machine-independent graph.
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
// flag: if this instruction is implemented with a call
if ( node_flags_set ) {
} else {
node_flags_set = true;
}
}
if ( node_flags_set ) {
}
// size_of, used by base class's clone to obtain the correct size.
// Virtual methods which are only generated to override base class
instr->is_mach_constant() ||
}
} else {
}
}
}
if ( instr->num_post_match_opnds() != 0
}
}
// Declare short branch methods, if applicable
// See if there is an "ins_pipe" declaration for this instruction
}
// Generate virtual function for MachNodeX::bottom_type when necessary
//
// Note on accuracy: Pointer-types of machine nodes need to be accurate,
// or else alias analysis on the matched graph may produce bad code.
// Moreover, the aliasing decisions made on machine-node graph must be
// no less accurate than those made on the ideal graph, or else the graph
// may fail to schedule. (Reason: Memory ops which are reordered in
// the ideal graph might look interdependent in the machine graph,
// thereby removing degrees of scheduling freedom that the optimizer
// assumed would be available.)
//
// %%% We should handle many of these cases with an explicit ADL clause:
// instruct foo() %{ ... bottom_type(TypeRawPtr::BOTTOM); ... %}
// A constant's bottom_type returns a Type containing its constant value
// !!!!!
// Convert all ints, floats, ... to machine-independent TypeXs
// as is done for pointers
//
// Construct appropriate constant type containing the constant value.
switch( data_type ) {
break;
break;
break;
break;
break;
default:
assert( false, "Unimplemented()" );
break;
}
}
/* else if ( instr->_matrule && instr->_matrule->_rChild &&
( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0
|| strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) {
// !!!!! !!!!!
// Provide explicit bottom type for conversions to int
// On Intel the result operand is a stackSlot, untyped.
fprintf(fp," virtual const class Type *bottom_type() const {");
fprintf(fp, " return TypeInt::INT;");
fprintf(fp, " };\n");
}*/
else if( instr->is_ideal_copy() &&
// !!!!!
// Special hack for ideal Copy of pointer. Bottom type is oop or not depending on input.
}
else if( instr->is_ideal_loadPC() ) {
// LoadPCNode provides the return address of a call to native code.
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
// since it is a pointer to an internal VM location and must have a zero offset.
// Allocation detects derived pointers, in part, by their non-zero offsets.
}
else if( instr->is_ideal_box() ) {
// BoxNode provides the address of a stack slot.
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
// This prevent s insert_anti_dependencies from complaining. It will
// complain if it sees that the pointer base is TypePtr::BOTTOM since
// it doesn't understand what that might alias.
}
else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveP") ) {
// Special special hack to see if the Cmp? has been incorporated in the conditional move
offset = 2;
}
// Special hack for ideal CMoveP; ideal type depends on inputs
fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveP\n",
}
else if( instr->_matrule && instr->_matrule->_rChild && !strcmp(instr->_matrule->_rChild->_opType,"CMoveN") ) {
// Special special hack to see if the Cmp? has been incorporated in the conditional move
offset = 2;
}
// Special hack for ideal CMoveN; ideal type depends on inputs
fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // CMoveN\n",
}
else if (instr->is_tls_instruction()) {
// Special hack for tlsLoadP
}
else if ( instr->is_ideal_if() ) {
}
else if ( instr->is_ideal_membar() ) {
}
// Check where 'ideal_type' must be customized
/*
if ( instr->_matrule && instr->_matrule->_rChild &&
( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0
|| strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) {
fprintf(fp," virtual uint ideal_reg() const { return Compile::current()->matcher()->base2reg[Type::Int]; }\n");
}*/
// Analyze machine instructions that either USE or DEF memory.
// Some guys kill all of memory
}
}
}
// virtual function for generating the user's assembler output
// Machine independent print functionality for debugging
// Close definition of this XxxMachNode
};
}
static const char *state__valid = "_valid[((uint)index) >> 5] & (0x1 << (((uint)index) & 0x0001F))";
static const char *state__set_valid= "_valid[((uint)index) >> 5] |= (0x1 << (((uint)index) & 0x0001F))";
"//---------------------------State-------------------------------------------\n");
fprintf(fp," unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entries\n");
if (_dfa_small) {
// Generate the routine name we'll need
for (int i = 1; i < _last_opcode; i++) {
}
}
}
//---------------------------buildMachOperEnum---------------------------------
// Build enumeration for densely packed operands.
// This enumeration is used to index into the arrays in the State objects
// that indicate cost and a successfull rule match.
// Information needed to generate the ReduceOp mapping for the DFA
public:
void declaration() { }
}
delete[] opc_ident_to_upper;
}
delete[] oper_ident_to_upper;
}
delete[] name_to_upper;
}
bool do_instructions() { return false; }
};
// Construct the table for MachOpcodes
}
//---------------------------buildMachEnum----------------------------------
// Build enumeration for all MachOpers and all MachNodes
// Information needed to generate the ReduceOp mapping for the DFA
int end_inst_chain_rule;
int begin_rematerialize;
int end_rematerialize;
int end_instructions;
public:
{};
void declaration() { }
void closing() {
if( begin_inst_chain_rule != -1 )
if( end_inst_chain_rule != -1 )
if( begin_rematerialize != -1 )
if( end_rematerialize != -1 )
// always execute since do_instructions() is true, and avoids trailing comma
}
switch(place) {
case OutputMap::BEGIN_INST_CHAIN_RULES :
break;
case OutputMap::END_INST_CHAIN_RULES :
break;
case OutputMap::BEGIN_REMATERIALIZE :
break;
case OutputMap::END_REMATERIALIZE :
break;
case OutputMap::END_INSTRUCTIONS :
break;
default:
break;
}
}
};
// Construct the table for MachOpcodes
}
// Generate an enumeration of the pipeline states, and both
// the functional units (resources) and the masks for
// specifying resources
int stagenum = 0;
if (_pipeline) { // Find max enum string length
const char *stage;
}
}
// Generate a list of stages
if( _pipeline ) {
const char *stage;
}
int rescount = 0;
if( _pipeline ) {
const char *resource;
int reslen = 0;
// Generate a list of resources, and masks
}
}
}
}
}