duke@435: /* twisti@1038: * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // FORMSSEL.HPP - ADL Parser Instruction Selection Forms Classes duke@435: duke@435: // Class List duke@435: class Form; duke@435: class InstructForm; duke@435: class MachNodeForm; duke@435: class OperandForm; duke@435: class OpClassForm; duke@435: class AttributeForm; duke@435: class RegisterForm; duke@435: class PipelineForm; duke@435: class SourceForm; duke@435: class EncodeForm; duke@435: class Component; duke@435: class Constraint; duke@435: class Predicate; duke@435: class MatchRule; duke@435: class Attribute; duke@435: class Effect; duke@435: class ExpandRule; duke@435: class RewriteRule; duke@435: class ConstructRule; duke@435: class FormatRule; duke@435: class Peephole; duke@435: class EncClass; duke@435: class Interface; duke@435: class RegInterface; duke@435: class ConstInterface; duke@435: class MemInterface; duke@435: class CondInterface; duke@435: class Opcode; duke@435: class InsEncode; duke@435: class RegDef; duke@435: class RegClass; duke@435: class AllocClass; duke@435: class ResourceForm; duke@435: class PipeDesc; duke@435: class PipeClass; duke@435: class PeepMatch; duke@435: class PeepConstraint; duke@435: class PeepReplace; duke@435: class MatchList; duke@435: duke@435: class ArchDesc; duke@435: duke@435: //==============================Instructions=================================== duke@435: //------------------------------InstructForm----------------------------------- duke@435: class InstructForm : public Form { duke@435: private: duke@435: bool _ideal_only; // Not a user-defined instruction duke@435: // Members used for tracking CISC-spilling duke@435: uint _cisc_spill_operand;// Which operand may cisc-spill duke@435: void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; } duke@435: bool _is_cisc_alternate; duke@435: InstructForm *_cisc_spill_alternate;// cisc possible replacement duke@435: const char *_cisc_reg_mask_name; duke@435: InstructForm *_short_branch_form; duke@435: bool _is_short_branch; duke@435: uint _alignment; duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_ident; // Name of this instruction duke@435: NameList _parameters; // Locally defined names duke@435: FormDict _localNames; // Table of operands & their types duke@435: MatchRule *_matrule; // Matching rule for this instruction duke@435: Opcode *_opcode; // Encoding of the opcode for instruction duke@435: char *_size; // Size of instruction duke@435: InsEncode *_insencode; // Encoding class instruction belongs to duke@435: Attribute *_attribs; // List of Attribute rules duke@435: Predicate *_predicate; // Predicate test for this instruction duke@435: FormDict _effects; // Dictionary of effect rules duke@435: ExpandRule *_exprule; // Expand rule for this instruction duke@435: RewriteRule *_rewrule; // Rewrite rule for this instruction duke@435: FormatRule *_format; // Format for assembly generation duke@435: Peephole *_peephole; // List of peephole rules for instruction duke@435: const char *_ins_pipe; // Instruction Scheduline description class duke@435: duke@435: uint *_uniq_idx; // Indexes of unique operands never@1034: int _uniq_idx_length; // Length of _uniq_idx array duke@435: uint _num_uniq; // Number of unique operands duke@435: ComponentList _components; // List of Components matches MachNode's duke@435: // operand structure duke@435: duke@435: // Public Methods duke@435: InstructForm(const char *id, bool ideal_only = false); duke@435: InstructForm(const char *id, InstructForm *instr, MatchRule *rule); duke@435: ~InstructForm(); duke@435: duke@435: // Dynamic type check duke@435: virtual InstructForm *is_instruction() const; duke@435: duke@435: virtual bool ideal_only() const; duke@435: duke@435: // This instruction sets a result duke@435: virtual bool sets_result() const; duke@435: // This instruction needs projections for additional DEFs or KILLs duke@435: virtual bool needs_projections(); duke@435: // This instruction needs extra nodes for temporary inputs duke@435: virtual bool has_temps(); duke@435: // This instruction defines or kills more than one object duke@435: virtual uint num_defs_or_kills(); duke@435: // This instruction has an expand rule? duke@435: virtual bool expands() const ; duke@435: // Return this instruction's first peephole rule, or NULL duke@435: virtual Peephole *peepholes() const; duke@435: // Add a peephole rule to this instruction duke@435: virtual void append_peephole(Peephole *peep); duke@435: duke@435: virtual bool is_pinned(FormDict &globals); // should be pinned inside block duke@435: virtual bool is_projection(FormDict &globals); // node requires projection duke@435: virtual bool is_parm(FormDict &globals); // node matches ideal 'Parm' duke@435: // ideal opcode enumeration duke@435: virtual const char *ideal_Opcode(FormDict &globals) const; duke@435: virtual int is_expensive() const; // node matches ideal 'CosD' duke@435: virtual int is_empty_encoding() const; // _size=0 and/or _insencode empty duke@435: virtual int is_tls_instruction() const; // tlsLoadP rule or ideal ThreadLocal duke@435: virtual int is_ideal_copy() const; // node matches ideal 'Copy*' duke@435: virtual bool is_ideal_unlock() const; // node matches ideal 'Unlock' duke@435: virtual bool is_ideal_call_leaf() const; // node matches ideal 'CallLeaf' duke@435: virtual bool is_ideal_if() const; // node matches ideal 'If' duke@435: virtual bool is_ideal_fastlock() const; // node matches 'FastLock' duke@435: virtual bool is_ideal_membar() const; // node matches ideal 'MemBarXXX' duke@435: virtual bool is_ideal_loadPC() const; // node matches ideal 'LoadPC' duke@435: virtual bool is_ideal_box() const; // node matches ideal 'Box' duke@435: virtual bool is_ideal_goto() const; // node matches ideal 'Goto' duke@435: virtual bool is_ideal_branch() const; // "" 'If' | 'Goto' | 'LoopEnd' | 'Jump' duke@435: virtual bool is_ideal_jump() const; // node matches ideal 'Jump' duke@435: virtual bool is_ideal_return() const; // node matches ideal 'Return' duke@435: virtual bool is_ideal_halt() const; // node matches ideal 'Halt' duke@435: virtual bool is_ideal_safepoint() const; // node matches 'SafePoint' duke@435: virtual bool is_ideal_nop() const; // node matches 'Nop' duke@435: virtual bool is_ideal_control() const; // control node duke@435: duke@435: virtual Form::CallType is_ideal_call() const; // matches ideal 'Call' duke@435: virtual Form::DataType is_ideal_load() const; // node matches ideal 'LoadXNode' duke@435: virtual Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode' duke@435: bool is_ideal_mem() const { return is_ideal_load() != Form::none || is_ideal_store() != Form::none; } duke@435: virtual uint two_address(FormDict &globals); // output reg must match input reg duke@435: // when chaining a constant to an instruction, return 'true' and set opType duke@435: virtual Form::DataType is_chain_of_constant(FormDict &globals); duke@435: virtual Form::DataType is_chain_of_constant(FormDict &globals, const char * &opType); duke@435: virtual Form::DataType is_chain_of_constant(FormDict &globals, const char * &opType, const char * &result_type); duke@435: duke@435: // Check if a simple chain rule duke@435: virtual bool is_simple_chain_rule(FormDict &globals) const; duke@435: duke@435: // check for structural rematerialization duke@435: virtual bool rematerialize(FormDict &globals, RegisterForm *registers); duke@435: duke@435: // loads from memory, so must check for anti-dependence duke@435: virtual bool needs_anti_dependence_check(FormDict &globals) const; duke@435: virtual int memory_operand(FormDict &globals) const; duke@435: bool is_wide_memory_kill(FormDict &globals) const; duke@435: duke@435: enum memory_operand_type { duke@435: NO_MEMORY_OPERAND = -1, duke@435: MANY_MEMORY_OPERANDS = 999999 duke@435: }; duke@435: duke@435: duke@435: // This instruction captures the machine-independent bottom_type duke@435: // Expected use is for pointer vs oop determination for LoadP duke@435: virtual bool captures_bottom_type() const; duke@435: duke@435: virtual const char *cost(); // Access ins_cost attribute duke@435: virtual uint num_opnds(); // Count of num_opnds for MachNode class duke@435: virtual uint num_post_match_opnds(); duke@435: virtual uint num_consts(FormDict &globals) const;// Constants in match rule duke@435: // Constants in match rule with specified type duke@435: virtual uint num_consts(FormDict &globals, Form::DataType type) const; duke@435: duke@435: // Return the register class associated with 'leaf'. duke@435: virtual const char *out_reg_class(FormDict &globals); duke@435: duke@435: // number of ideal node inputs to skip duke@435: virtual uint oper_input_base(FormDict &globals); duke@435: duke@435: // Does this instruction need a base-oop edge? duke@435: int needs_base_oop_edge(FormDict &globals) const; duke@435: duke@435: // Build instruction predicates. If the user uses the same operand name duke@435: // twice, we need to check that the operands are pointer-eequivalent in duke@435: // the DFA during the labeling process. duke@435: Predicate *build_predicate(); duke@435: duke@435: virtual void build_components(); // top-level operands duke@435: // Return zero-based position in component list; -1 if not in list. duke@435: virtual int operand_position(const char *name, int usedef); duke@435: virtual int operand_position_format(const char *name); duke@435: duke@435: // Return zero-based position in component list; -1 if not in list. duke@435: virtual int label_position(); duke@435: virtual int method_position(); duke@435: // Return number of relocation entries needed for this instruction. duke@435: virtual uint reloc(FormDict &globals); duke@435: duke@435: const char *reduce_result(); duke@435: // Return the name of the operand on the right hand side of the binary match duke@435: // Return NULL if there is no right hand side duke@435: const char *reduce_right(FormDict &globals) const; duke@435: const char *reduce_left(FormDict &globals) const; duke@435: duke@435: // Base class for this instruction, MachNode except for calls duke@435: virtual const char *mach_base_class() const; duke@435: duke@435: // Check if this instruction can cisc-spill to 'alternate' duke@435: bool cisc_spills_to(ArchDesc &AD, InstructForm *alternate); duke@435: InstructForm *cisc_spill_alternate() { return _cisc_spill_alternate; } duke@435: uint cisc_spill_operand() const { return _cisc_spill_operand; } duke@435: bool is_cisc_alternate() const { return _is_cisc_alternate; } duke@435: void set_cisc_alternate(bool val) { _is_cisc_alternate = val; } duke@435: const char *cisc_reg_mask_name() const { return _cisc_reg_mask_name; } duke@435: void set_cisc_reg_mask_name(const char *rm_name) { _cisc_reg_mask_name = rm_name; } duke@435: // Output cisc-method prototypes and method bodies duke@435: void declare_cisc_version(ArchDesc &AD, FILE *fp_cpp); duke@435: bool define_cisc_version (ArchDesc &AD, FILE *fp_cpp); duke@435: duke@435: bool check_branch_variant(ArchDesc &AD, InstructForm *short_branch); duke@435: duke@435: bool is_short_branch() { return _is_short_branch; } duke@435: void set_short_branch(bool val) { _is_short_branch = val; } duke@435: duke@435: InstructForm *short_branch_form() { return _short_branch_form; } duke@435: bool has_short_branch_form() { return _short_branch_form != NULL; } duke@435: // Output short branch prototypes and method bodies duke@435: void declare_short_branch_methods(FILE *fp_cpp); duke@435: bool define_short_branch_methods(FILE *fp_cpp); duke@435: duke@435: uint alignment() { return _alignment; } duke@435: void set_alignment(uint val) { _alignment = val; } duke@435: duke@435: // Seach through operands to determine operands unique positions. duke@435: void set_unique_opnds(); duke@435: uint num_unique_opnds() { return _num_uniq; } duke@435: uint unique_opnds_idx(int idx) { never@1034: if( _uniq_idx != NULL && idx > 0 ) { never@1034: assert(idx < _uniq_idx_length, "out of bounds"); duke@435: return _uniq_idx[idx]; never@1034: } else { duke@435: return idx; never@1034: } never@1034: } duke@435: duke@435: // Operands which are only KILLs aren't part of the input array and duke@435: // require special handling in some cases. Their position in this duke@435: // operand list is higher than the number of unique operands. duke@435: bool is_noninput_operand(uint idx) { duke@435: return (idx >= num_unique_opnds()); duke@435: } duke@435: duke@435: // --------------------------- FILE *output_routines duke@435: // duke@435: // Generate the format call for the replacement variable duke@435: void rep_var_format(FILE *fp, const char *rep_var); twisti@1040: // Generate index values needed for determining the operand position duke@435: void index_temps (FILE *fp, FormDict &globals, const char *prefix = "", const char *receiver = ""); duke@435: // --------------------------- duke@435: duke@435: virtual bool verify(); // Check consistency after parsing duke@435: duke@435: virtual void dump(); // Debug printer duke@435: virtual void output(FILE *fp); // Write to output files duke@435: }; duke@435: duke@435: //------------------------------EncodeForm------------------------------------- duke@435: class EncodeForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: NameList _eclasses; // List of encode class names duke@435: Dict _encClass; // Map encode class names to EncClass objects duke@435: duke@435: // Public Methods duke@435: EncodeForm(); duke@435: ~EncodeForm(); duke@435: duke@435: EncClass *add_EncClass(const char *className); duke@435: EncClass *encClass(const char *className); duke@435: duke@435: const char *encClassPrototype(const char *className); duke@435: const char *encClassBody(const char *className); duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------EncClass--------------------------------------- duke@435: class EncClass : public Form { duke@435: public: duke@435: // NameList for parameter type and name duke@435: NameList _parameter_type; duke@435: NameList _parameter_name; duke@435: duke@435: // Breakdown the encoding into strings separated by $replacement_variables duke@435: // There is an entry in _strings, perhaps NULL, that precedes each _rep_vars duke@435: NameList _code; // Strings passed through to tty->print duke@435: NameList _rep_vars; // replacement variables duke@435: duke@435: NameList _parameters; // Locally defined names duke@435: FormDict _localNames; // Table of components & their types duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_name; // encoding class name duke@435: duke@435: // Public Methods duke@435: EncClass(const char *name); duke@435: ~EncClass(); duke@435: duke@435: // --------------------------- Parameters duke@435: // Add a parameter pair duke@435: void add_parameter(const char *parameter_type, const char *parameter_name); duke@435: // Verify operand types in parameter list duke@435: bool check_parameter_types(FormDict &globals); duke@435: // Obtain the zero-based index corresponding to a replacement variable duke@435: int rep_var_index(const char *rep_var); duke@435: int num_args() { return _parameter_name.count(); } duke@435: duke@435: // --------------------------- Code Block duke@435: // Add code twisti@1040: void add_code(const char *string_preceding_replacement_var); duke@435: // Add a replacement variable or one of its subfields duke@435: // Subfields are stored with a leading '$' duke@435: void add_rep_var(char *replacement_var); duke@435: duke@435: bool verify(); duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------MachNode--------------------------------------- duke@435: class MachNodeForm: public Form { duke@435: private: duke@435: duke@435: public: duke@435: char *_ident; // Name of this instruction duke@435: const char *_machnode_pipe; // Instruction Scheduline description class duke@435: duke@435: // Public Methods duke@435: MachNodeForm(char *id); duke@435: ~MachNodeForm(); duke@435: duke@435: virtual MachNodeForm *is_machnode() const; duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------Opcode----------------------------------------- duke@435: class Opcode : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: // Strings representing instruction opcodes, user defines placement in emit duke@435: char *_primary; duke@435: char *_secondary; duke@435: char *_tertiary; duke@435: duke@435: enum opcode_type { duke@435: NOT_AN_OPCODE = -1, duke@435: PRIMARY = 1, duke@435: SECONDARY = 2, duke@435: TERTIARY = 3 duke@435: }; duke@435: duke@435: // Public Methods duke@435: Opcode(char *primary, char *secondary, char *tertiary); duke@435: ~Opcode(); duke@435: duke@435: static Opcode::opcode_type as_opcode_type(const char *designator); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: duke@435: // --------------------------- FILE *output_routines never@850: bool print_opcode(FILE *fp, Opcode::opcode_type desired_opcode); duke@435: }; duke@435: duke@435: //------------------------------InsEncode-------------------------------------- duke@435: class InsEncode : public Form { duke@435: private: duke@435: // Public Data (access directly only for reads) duke@435: // The encodings can only have the values predefined by the ADLC: duke@435: // blank, RegReg, RegMem, MemReg, ... duke@435: NameList _encoding; duke@435: // NameList _parameter; duke@435: // The parameters for each encoding are preceeded by a NameList::_signal duke@435: // and follow the parameters for the previous encoding. duke@435: duke@435: // char *_encode; // Type of instruction encoding duke@435: duke@435: public: duke@435: // Public Methods duke@435: InsEncode(); duke@435: ~InsEncode(); duke@435: duke@435: // Add "encode class name" and its parameters duke@435: NameAndList *add_encode(char *encode_method_name); duke@435: // Parameters are added to the returned "NameAndList" by the parser duke@435: duke@435: // Access the list of encodings duke@435: void reset(); duke@435: const char *encode_class_iter(); duke@435: duke@435: // Returns the number of arguments to the current encoding in the iteration duke@435: int current_encoding_num_args() { duke@435: return ((NameAndList*)_encoding.current())->count(); duke@435: } duke@435: duke@435: // --------------------------- Parameters duke@435: // The following call depends upon position within encode_class_iteration duke@435: // duke@435: // Obtain parameter name from zero based index duke@435: const char *rep_var_name(InstructForm &inst, uint param_no); duke@435: // --------------------------- duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------Effect----------------------------------------- duke@435: class Effect : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_name; // Pre-defined name for effect duke@435: int _use_def; // Enumeration value of effect duke@435: duke@435: // Public Methods duke@435: Effect(const char *name); // Constructor duke@435: ~Effect(); // Destructor duke@435: duke@435: // Dynamic type check duke@435: virtual Effect *is_effect() const; duke@435: duke@435: // Return 'true' if this use def info equals the parameter duke@435: bool is(int use_def_kill_enum) const; duke@435: // Return 'true' if this use def info is a superset of parameter duke@435: bool isa(int use_def_kill_enum) const; duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------ExpandRule------------------------------------- duke@435: class ExpandRule : public Form { duke@435: private: duke@435: NameList _expand_instrs; // ordered list of instructions and operands duke@435: duke@435: public: duke@435: // Public Data duke@435: NameList _newopers; // List of newly created operands duke@435: Dict _newopconst; // Map new operands to their constructors duke@435: duke@435: void add_instruction(NameAndList *instruction_name_and_operand_list); duke@435: void reset_instructions(); duke@435: NameAndList *iter_instructions(); duke@435: duke@435: // Public Methods duke@435: ExpandRule(); // Constructor duke@435: ~ExpandRule(); // Destructor duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------RewriteRule------------------------------------ duke@435: class RewriteRule : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: SourceForm *_condition; // Rewrite condition code duke@435: InstructForm *_instrs; // List of instructions to expand to duke@435: OperandForm *_opers; // List of operands generated by expand duke@435: char *_tempParams; // Hold string until parser is finished. duke@435: char *_tempBlock; // Hold string until parser is finished. duke@435: duke@435: // Public Methods duke@435: RewriteRule(char* params, char* block) ; duke@435: ~RewriteRule(); // Destructor duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: duke@435: //==============================Operands======================================= duke@435: //------------------------------OpClassForm------------------------------------ duke@435: class OpClassForm : public Form { duke@435: public: duke@435: // Public Data duke@435: const char *_ident; // Name of this operand duke@435: NameList _oplst; // List of operand forms included in class duke@435: duke@435: // Public Methods duke@435: OpClassForm(const char *id); duke@435: ~OpClassForm(); duke@435: duke@435: // dynamic type check duke@435: virtual OpClassForm *is_opclass() const; duke@435: virtual Form::InterfaceType interface_type(FormDict &globals) const; duke@435: virtual bool stack_slots_only(FormDict &globals) const; duke@435: duke@435: virtual bool is_cisc_mem(FormDict &globals) const; duke@435: duke@435: duke@435: // Min and Max opcodes of operands in this operand class duke@435: int _minCode; duke@435: int _maxCode; duke@435: duke@435: virtual bool ideal_only() const; duke@435: virtual void dump(); // Debug printer duke@435: virtual void output(FILE *fp); // Write to output files duke@435: }; duke@435: duke@435: //------------------------------OperandForm------------------------------------ duke@435: class OperandForm : public OpClassForm { duke@435: private: duke@435: bool _ideal_only; // Not a user-defined instruction duke@435: duke@435: public: duke@435: // Public Data duke@435: NameList _parameters; // Locally defined names duke@435: FormDict _localNames; // Table of components & their types duke@435: MatchRule *_matrule; // Matching rule for this operand duke@435: Interface *_interface; // Encoding interface for this operand duke@435: Attribute *_attribs; // List of Attribute rules duke@435: Predicate *_predicate; // Predicate test for this operand duke@435: Constraint *_constraint; // Constraint Rule for this operand duke@435: ConstructRule *_construct; // Construction of operand data after matching duke@435: FormatRule *_format; // Format for assembly generation duke@435: NameList _classes; // List of opclasses which contain this oper duke@435: duke@435: ComponentList _components; // duke@435: duke@435: // Public Methods duke@435: OperandForm(const char *id); duke@435: OperandForm(const char *id, bool ideal_only); duke@435: ~OperandForm(); duke@435: duke@435: // Dynamic type check duke@435: virtual OperandForm *is_operand() const; duke@435: duke@435: virtual bool ideal_only() const; duke@435: virtual Form::InterfaceType interface_type(FormDict &globals) const; duke@435: virtual bool stack_slots_only(FormDict &globals) const; duke@435: duke@435: virtual const char *cost(); // Access ins_cost attribute duke@435: virtual uint num_leaves() const;// Leaves in complex operand duke@435: // Constants in operands' match rules duke@435: virtual uint num_consts(FormDict &globals) const; duke@435: // Constants in operand's match rule with specified type duke@435: virtual uint num_consts(FormDict &globals, Form::DataType type) const; duke@435: // Pointer Constants in operands' match rules duke@435: virtual uint num_const_ptrs(FormDict &globals) const; duke@435: // The number of input edges in the machine world == num_leaves - num_consts duke@435: virtual uint num_edges(FormDict &globals) const; duke@435: duke@435: // Check if this operand is usable for cisc-spilling duke@435: virtual bool is_cisc_reg(FormDict &globals) const; duke@435: duke@435: // node matches ideal 'Bool', grab condition codes from the ideal world duke@435: virtual bool is_ideal_bool() const; duke@435: duke@435: // Has an integer constant suitable for spill offsets duke@435: bool has_conI(FormDict &globals) const { duke@435: return (num_consts(globals,idealI) == 1) && !is_ideal_bool(); } duke@435: bool has_conL(FormDict &globals) const { duke@435: return (num_consts(globals,idealL) == 1) && !is_ideal_bool(); } duke@435: duke@435: // Node is user-defined operand for an sRegX duke@435: virtual Form::DataType is_user_name_for_sReg() const; duke@435: duke@435: // Return ideal type, if there is a single ideal type for this operand duke@435: virtual const char *ideal_type(FormDict &globals, RegisterForm *registers = NULL) const; duke@435: // If there is a single ideal type for this interface field, return it. duke@435: virtual const char *interface_ideal_type(FormDict &globals, duke@435: const char *field_name) const; duke@435: duke@435: // Return true if this operand represents a bound register class duke@435: bool is_bound_register() const; duke@435: duke@435: // Return the Register class for this operand. Returns NULL if duke@435: // operand isn't a register form. duke@435: RegClass* get_RegClass() const; duke@435: duke@435: virtual bool is_interface_field(const char *field_name, duke@435: const char * &value) const; duke@435: duke@435: // If this operand has a single ideal type, return its type duke@435: virtual Form::DataType simple_type(FormDict &globals) const; duke@435: // If this operand is an ideal constant, return its type duke@435: virtual Form::DataType is_base_constant(FormDict &globals) const; duke@435: duke@435: // "true" if this operand is a simple type that is swallowed duke@435: virtual bool swallowed(FormDict &globals) const; duke@435: duke@435: // Return register class name if a constraint specifies the register class. duke@435: virtual const char *constrained_reg_class() const; duke@435: // Return the register class associated with 'leaf'. duke@435: virtual const char *in_reg_class(uint leaf, FormDict &globals); duke@435: duke@435: // Build component list from MatchRule and operand's parameter list duke@435: virtual void build_components(); // top-level operands duke@435: duke@435: // Return zero-based position in component list; -1 if not in list. duke@435: virtual int operand_position(const char *name, int usedef); duke@435: duke@435: // Return zero-based position in component list; -1 if not in list. duke@435: virtual int constant_position(FormDict &globals, const Component *comp); duke@435: virtual int constant_position(FormDict &globals, const char *local_name); duke@435: // Return the operand form corresponding to the given index, else NULL. duke@435: virtual OperandForm *constant_operand(FormDict &globals, uint const_index); duke@435: duke@435: // Return zero-based position in component list; -1 if not in list. duke@435: virtual int register_position(FormDict &globals, const char *regname); duke@435: duke@435: const char *reduce_result() const; duke@435: // Return the name of the operand on the right hand side of the binary match duke@435: // Return NULL if there is no right hand side duke@435: const char *reduce_right(FormDict &globals) const; duke@435: const char *reduce_left(FormDict &globals) const; duke@435: duke@435: duke@435: // --------------------------- FILE *output_routines duke@435: // duke@435: // Output code for disp_is_oop, if true. duke@435: void disp_is_oop(FILE *fp, FormDict &globals); duke@435: // Generate code for internal and external format methods duke@435: void int_format(FILE *fp, FormDict &globals, uint index); duke@435: void ext_format(FILE *fp, FormDict &globals, uint index); duke@435: void format_constant(FILE *fp, uint con_index, uint con_type); duke@435: // Output code to access the value of the index'th constant duke@435: void access_constant(FILE *fp, FormDict &globals, duke@435: uint con_index); duke@435: // --------------------------- duke@435: duke@435: duke@435: virtual void dump(); // Debug printer duke@435: virtual void output(FILE *fp); // Write to output files duke@435: }; duke@435: duke@435: //------------------------------Constraint------------------------------------- duke@435: class Constraint : public Form { duke@435: private: duke@435: duke@435: public: duke@435: const char *_func; // Constraint function duke@435: const char *_arg; // function's argument duke@435: duke@435: // Public Methods duke@435: Constraint(const char *func, const char *arg); // Constructor duke@435: ~Constraint(); duke@435: duke@435: bool stack_slots_only() const; duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------Predicate-------------------------------------- duke@435: class Predicate : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_pred; // C++ source string for predicate duke@435: duke@435: // Public Methods duke@435: Predicate(char *pr); duke@435: ~Predicate(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------Interface-------------------------------------- duke@435: class Interface : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_name; // String representing the interface name duke@435: duke@435: // Public Methods duke@435: Interface(const char *name); duke@435: ~Interface(); duke@435: duke@435: virtual Form::InterfaceType interface_type(FormDict &globals) const; duke@435: duke@435: RegInterface *is_RegInterface(); duke@435: MemInterface *is_MemInterface(); duke@435: ConstInterface *is_ConstInterface(); duke@435: CondInterface *is_CondInterface(); duke@435: duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------RegInterface----------------------------------- duke@435: class RegInterface : public Interface { duke@435: private: duke@435: duke@435: public: duke@435: // Public Methods duke@435: RegInterface(); duke@435: ~RegInterface(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------ConstInterface--------------------------------- duke@435: class ConstInterface : public Interface { duke@435: private: duke@435: duke@435: public: duke@435: // Public Methods duke@435: ConstInterface(); duke@435: ~ConstInterface(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------MemInterface----------------------------------- duke@435: class MemInterface : public Interface { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_base; // Base address duke@435: char *_index; // index duke@435: char *_scale; // scaling factor duke@435: char *_disp; // displacement duke@435: duke@435: // Public Methods duke@435: MemInterface(char *base, char *index, char *scale, char *disp); duke@435: ~MemInterface(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------CondInterface---------------------------------- duke@435: class CondInterface : public Interface { duke@435: private: duke@435: duke@435: public: duke@435: const char *_equal; duke@435: const char *_not_equal; duke@435: const char *_less; duke@435: const char *_greater_equal; duke@435: const char *_less_equal; duke@435: const char *_greater; never@850: const char *_equal_format; never@850: const char *_not_equal_format; never@850: const char *_less_format; never@850: const char *_greater_equal_format; never@850: const char *_less_equal_format; never@850: const char *_greater_format; duke@435: duke@435: // Public Methods never@850: CondInterface(const char* equal, const char* equal_format, never@850: const char* not_equal, const char* not_equal_format, never@850: const char* less, const char* less_format, never@850: const char* greater_equal, const char* greater_equal_format, never@850: const char* less_equal, const char* less_equal_format, never@850: const char* greater, const char* greater_format); duke@435: ~CondInterface(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------ConstructRule---------------------------------- duke@435: class ConstructRule : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_expr; // String representing the match expression duke@435: char *_construct; // String representing C++ constructor code duke@435: duke@435: // Public Methods duke@435: ConstructRule(char *cnstr); duke@435: ~ConstructRule(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: duke@435: //==============================Shared========================================= duke@435: //------------------------------AttributeForm---------------------------------- duke@435: class AttributeForm : public Form { duke@435: private: duke@435: // counters for unique instruction or operand ID duke@435: static int _insId; // user-defined machine instruction types duke@435: static int _opId; // user-defined operand types duke@435: duke@435: int id; // hold type for this object duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_attrname; // Name of attribute duke@435: int _atype; // Either INS_ATTR or OP_ATTR duke@435: char *_attrdef; // C++ source which evaluates to constant duke@435: duke@435: // Public Methods duke@435: AttributeForm(char *attr, int type, char *attrdef); duke@435: ~AttributeForm(); duke@435: duke@435: // Dynamic type check duke@435: virtual AttributeForm *is_attribute() const; duke@435: duke@435: int type() { return id;} // return this object's "id" duke@435: duke@435: static const char* _ins_cost; // "ins_cost" duke@435: static const char* _ins_pc_relative; // "ins_pc_relative" duke@435: static const char* _op_cost; // "op_cost" duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write output files duke@435: }; duke@435: duke@435: //------------------------------Component-------------------------------------- duke@435: class Component : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_name; // Name of this component duke@435: const char *_type; // Type of this component duke@435: int _usedef; // Value of component duke@435: duke@435: // Public Methods duke@435: Component(const char *name, const char *type, int usedef); duke@435: ~Component(); duke@435: duke@435: duke@435: // Return 'true' if this use def info equals the parameter duke@435: bool is(int use_def_kill_enum) const; duke@435: // Return 'true' if this use def info is a superset of parameter duke@435: bool isa(int use_def_kill_enum) const; duke@435: int promote_use_def_info(int new_use_def); duke@435: const char *base_type(FormDict &globals); duke@435: // Form::DataType is_base_constant(FormDict &globals); duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write to output files duke@435: duke@435: public: duke@435: // Implementation depends upon working bit intersection and union. duke@435: enum use_def_enum { duke@435: INVALID = 0x0, duke@435: USE = 0x1, duke@435: DEF = 0x2, USE_DEF = 0x3, duke@435: KILL = 0x4, USE_KILL = 0x5, duke@435: SYNTHETIC = 0x8, duke@435: TEMP = USE | SYNTHETIC duke@435: }; duke@435: }; duke@435: duke@435: duke@435: //------------------------------MatchNode-------------------------------------- duke@435: class MatchNode : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_result; // The name of the output of this node duke@435: const char *_name; // The name that appeared in the match rule duke@435: const char *_opType; // The Operation/Type matched duke@435: MatchNode *_lChild; // Left child in expression tree duke@435: MatchNode *_rChild; // Right child in expression tree duke@435: int _numleaves; // Sum of numleaves for all direct children duke@435: ArchDesc &_AD; // Reference to ArchDesc object duke@435: char *_internalop; // String representing internal operand duke@435: int _commutative_id; // id of commutative operation duke@435: duke@435: // Public Methods duke@435: MatchNode(ArchDesc &ad, const char *result = 0, const char *expr = 0, duke@435: const char *opType=0, MatchNode *lChild=NULL, duke@435: MatchNode *rChild=NULL); duke@435: MatchNode(ArchDesc &ad, MatchNode& mNode); // Shallow copy constructor; duke@435: MatchNode(ArchDesc &ad, MatchNode& mNode, int clone); // Construct clone duke@435: ~MatchNode(); duke@435: duke@435: // return 0 if not found: duke@435: // return 1 if found and position is incremented by operand offset in rule duke@435: bool find_name(const char *str, int &position) const; duke@435: bool find_type(const char *str, int &position) const; twisti@1038: virtual void append_components(FormDict& locals, ComponentList& components, twisti@1038: bool def_flag = false) const; duke@435: bool base_operand(uint &position, FormDict &globals, duke@435: const char * &result, const char * &name, duke@435: const char * &opType) const; duke@435: // recursive count on operands duke@435: uint num_consts(FormDict &globals) const; duke@435: uint num_const_ptrs(FormDict &globals) const; duke@435: // recursive count of constants with specified type duke@435: uint num_consts(FormDict &globals, Form::DataType type) const; duke@435: // uint num_consts() const; // Local inspection only duke@435: int needs_ideal_memory_edge(FormDict &globals) const; duke@435: int needs_base_oop_edge() const; duke@435: duke@435: // Help build instruction predicates. Search for operand names. duke@435: void count_instr_names( Dict &names ); duke@435: int build_instr_pred( char *buf, const char *name, int cnt ); duke@435: void build_internalop( ); duke@435: duke@435: // Return the name of the operands associated with reducing to this operand: duke@435: // The result type, plus the left and right sides of the binary match duke@435: // Return NULL if there is no left or right hand side duke@435: bool sets_result() const; // rule "Set"s result of match duke@435: const char *reduce_right(FormDict &globals) const; duke@435: const char *reduce_left (FormDict &globals) const; duke@435: duke@435: // Recursive version of check in MatchRule twisti@1038: int cisc_spill_match(FormDict& globals, RegisterForm* registers, twisti@1038: MatchNode* mRule2, const char* &operand, twisti@1038: const char* ®_type); duke@435: int cisc_spill_merge(int left_result, int right_result); duke@435: twisti@1038: virtual bool equivalent(FormDict& globals, MatchNode* mNode2); duke@435: duke@435: void count_commutative_op(int& count); duke@435: void swap_commutative_op(bool atroot, int count); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------MatchRule-------------------------------------- duke@435: class MatchRule : public MatchNode { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_machType; // Machine type index duke@435: int _depth; // Expression tree depth duke@435: char *_construct; // String representing C++ constructor code duke@435: int _numchilds; // Number of direct children duke@435: MatchRule *_next; // Pointer to next match rule duke@435: duke@435: // Public Methods duke@435: MatchRule(ArchDesc &ad); duke@435: MatchRule(ArchDesc &ad, MatchRule* mRule); // Shallow copy constructor; duke@435: MatchRule(ArchDesc &ad, MatchNode* mroot, int depth, char* construct, int numleaves); duke@435: ~MatchRule(); duke@435: twisti@1038: virtual void append_components(FormDict& locals, ComponentList& components, bool def_flag = false) const; duke@435: // Recursive call on all operands' match rules in my match rule. duke@435: bool base_operand(uint &position, FormDict &globals, duke@435: const char * &result, const char * &name, duke@435: const char * &opType) const; duke@435: duke@435: duke@435: bool is_base_register(FormDict &globals) const; duke@435: Form::DataType is_base_constant(FormDict &globals) const; duke@435: bool is_chain_rule(FormDict &globals) const; duke@435: int is_ideal_copy() const; duke@435: int is_expensive() const; // node matches ideal 'CosD' duke@435: bool is_ideal_unlock() const; duke@435: bool is_ideal_call_leaf() const; duke@435: bool is_ideal_if() const; // node matches ideal 'If' duke@435: bool is_ideal_fastlock() const; // node matches ideal 'FastLock' duke@435: bool is_ideal_jump() const; // node matches ideal 'Jump' duke@435: bool is_ideal_membar() const; // node matches ideal 'MemBarXXX' duke@435: bool is_ideal_loadPC() const; // node matches ideal 'LoadPC' duke@435: bool is_ideal_box() const; // node matches ideal 'Box' duke@435: bool is_ideal_goto() const; // node matches ideal 'Goto' duke@435: bool is_ideal_loopEnd() const; // node matches ideal 'LoopEnd' duke@435: bool is_ideal_bool() const; // node matches ideal 'Bool' duke@435: Form::DataType is_ideal_load() const;// node matches ideal 'LoadXNode' duke@435: Form::DataType is_ideal_store() const;// node matches ideal 'StoreXNode' duke@435: duke@435: // Check if 'mRule2' is a cisc-spill variant of this MatchRule twisti@1038: int matchrule_cisc_spill_match(FormDict &globals, RegisterForm* registers, twisti@1038: MatchRule* mRule2, const char* &operand, twisti@1038: const char* ®_type); duke@435: duke@435: // Check if 'mRule2' is equivalent to this MatchRule twisti@1038: virtual bool equivalent(FormDict& globals, MatchNode* mRule2); duke@435: twisti@1038: void matchrule_swap_commutative_op(const char* instr_ident, int count, int& match_rules_cnt); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------Attribute-------------------------------------- duke@435: class Attribute : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_ident; // Name of predefined attribute duke@435: char *_val; // C++ source which evaluates to constant duke@435: int _atype; // Either INS_ATTR or OP_ATTR duke@435: int int_val(ArchDesc &ad); // Return atoi(_val), ensuring syntax. duke@435: duke@435: // Public Methods duke@435: Attribute(char *id, char* val, int type); duke@435: ~Attribute(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: //------------------------------FormatRule------------------------------------- duke@435: class FormatRule : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: // There is an entry in _strings, perhaps NULL, that precedes each _rep_vars duke@435: NameList _strings; // Strings passed through to tty->print duke@435: NameList _rep_vars; // replacement variables duke@435: char *_temp; // String representing the assembly code duke@435: duke@435: // Public Methods duke@435: FormatRule(char *temp); duke@435: ~FormatRule(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: };