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