X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbearch_t.h;h=e7c0320b7cbb4f6d838d1252e95b59e7317b1321;hb=f2c2e45eb4e677fef5bf6a8e418b2a22441172d5;hp=4402cc4ec658b25b99ffd9e690acd727cfc8dbd7;hpb=d6768d8d4427959eb045aafb1d15bd189beaa5dd;p=libfirm diff --git a/ir/be/bearch_t.h b/ir/be/bearch_t.h index 4402cc4ec..e7c0320b7 100644 --- a/ir/be/bearch_t.h +++ b/ir/be/bearch_t.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -32,7 +32,9 @@ #include "beilpsched.h" #include "bemachine.h" #include "beirg.h" +#include "beinfo.h" #include "beabi.h" +#include "raw_bitset.h" /** * A register. @@ -40,23 +42,24 @@ struct arch_register_t { const char *name; /**< The name of the register. */ const arch_register_class_t *reg_class; /**< The class the register belongs to. */ - int index; /**< The index of the register in the class. */ + unsigned index; /**< The index of the register in the class. */ arch_register_type_t type; /**< The type of the register. */ - void *data; /**< Custom data. */ }; -static INLINE const arch_register_class_t * +static inline const arch_register_class_t * _arch_register_get_class(const arch_register_t *reg) { return reg->reg_class; } -static INLINE int _arch_register_get_index(const arch_register_t *reg) +static inline +unsigned _arch_register_get_index(const arch_register_t *reg) { return reg->index; } -static INLINE const char *_arch_register_get_name(const arch_register_t *reg) +static inline +const char *_arch_register_get_name(const arch_register_t *reg) { return reg->name; } @@ -79,10 +82,13 @@ static INLINE const char *_arch_register_get_name(const arch_register_t *reg) * Like general purpose or floating point. */ struct arch_register_class_t { - const char *name; /**< The name of the register class. */ - int n_regs; /**< Number of registers in this class. */ - ir_mode *mode; /**< The mode of the register class. */ - const arch_register_t *regs; /**< The array of registers. */ + unsigned index; /**< index of this register class */ + const char *name; /**< The name of the register class.*/ + unsigned n_regs; /**< Number of registers in this + class. */ + ir_mode *mode; /**< The mode of the register class.*/ + const arch_register_t *regs; /**< The array of registers. */ + arch_register_class_flags_t flags; /**< register class flags. */ }; /** return the number of registers in this register class */ @@ -94,10 +100,16 @@ struct arch_register_class_t { /** return the name of this register class */ #define arch_register_class_name(cls) ((cls)->name) -static INLINE const arch_register_t * -_arch_register_for_index(const arch_register_class_t *cls, int idx) +/** return the index of this register class */ +#define arch_register_class_index(cls) ((cls)->index) + +/** return the register class flags */ +#define arch_register_class_flags(cls) ((cls)->flags) + +static inline const arch_register_t * +_arch_register_for_index(const arch_register_class_t *cls, unsigned idx) { - assert(0 <= idx && idx < cls->n_regs); + assert(idx < cls->n_regs); return &cls->regs[idx]; } @@ -121,17 +133,38 @@ struct arch_register_req_t { const unsigned *limited; /**< allowed register bitset */ - int other_same; /**< The in number which shall have - the same res (should_be_same)*/ - int other_different; /**< The other node from which this - one's register must be different - (case must_be_different). */ + unsigned other_same; /**< Bitmask of ins which should use the + same register (should_be_same). */ + unsigned other_different; /**< Bitmask of ins which shall use a + different register + (must_be_different) */ }; -struct arch_flag_t { - const char *name; - unsigned index; -}; +static inline int reg_reqs_equal(const arch_register_req_t *req1, + const arch_register_req_t *req2) +{ + if (req1 == req2) + return 1; + + if (req1->type != req2->type + || req1->cls != req2->cls + || req1->other_same != req2->other_same + || req1->other_different != req2->other_different) + return 0; + + if (req1->limited != NULL) { + size_t n_regs; + + if (req2->limited == NULL) + return 0; + + n_regs = arch_register_class_n_regs(req1->cls); + if (!rbitset_equal(req1->limited, req2->limited, n_regs)) + return 0; + } + + return 1; +} /** * An inverse operation returned by the backend @@ -146,53 +179,24 @@ struct arch_inverse_t { ir_node **nodes; }; -struct arch_irn_ops_if_t { +struct arch_irn_ops_t { /** * Get the register requirements for a given operand. * @param self The self pointer. * @param irn The node. - * @param pos The operand's position - * (-1 for the result of the node, 0..n for the input operands). + * @param pos The operand's position (0..n for the input operands). * @return The register requirements for the selected operand. * The pointer returned is never NULL. */ - const arch_register_req_t *(*get_irn_reg_req)(const void *self, - const ir_node *irn, int pos); - - /** - * Set the register for an output operand. - * @param irn The node. - * @param reg The register allocated to that operand. - * @note If the operand is not a register operand, - * the call is ignored. - */ - void (*set_irn_reg)(const void *self, ir_node *irn, const arch_register_t *reg); - - /** - * Get the register allocated for an output operand. - * @param irn The node. - * @return The register allocated at that operand. NULL, if - * the operand was no register operand or - * @c arch_register_invalid, if no register has yet been - * allocated for this node. - */ - const arch_register_t *(*get_irn_reg)(const void *self, const ir_node *irn); + const arch_register_req_t *(*get_irn_reg_req)(const ir_node *irn, int pos); /** * Classify the node. * @param irn The node. * @return A classification. */ - arch_irn_class_t (*classify)(const void *self, const ir_node *irn); - - /** - * Get the flags of a node. - * @param self The irn ops themselves. - * @param irn The node. - * @return A set of flags. - */ - arch_irn_flags_t (*get_flags)(const void *self, const ir_node *irn); + arch_irn_class_t (*classify)(const ir_node *irn); /** * Get the entity on the stack frame this node depends on. @@ -201,7 +205,7 @@ struct arch_irn_ops_if_t { * @return The entity on the stack frame or NULL, if the node does not have a * stack frame entity. */ - ir_entity *(*get_frame_entity)(const void *self, const ir_node *irn); + ir_entity *(*get_frame_entity)(const ir_node *irn); /** * Set the entity on the stack frame this node depends on. @@ -209,7 +213,7 @@ struct arch_irn_ops_if_t { * @param irn The node in question. * @param ent The entity to set */ - void (*set_frame_entity)(const void *self, ir_node *irn, ir_entity *ent); + void (*set_frame_entity)(ir_node *irn, ir_entity *ent); /** * Set the offset of a node carrying an entity on the stack frame. @@ -217,7 +221,7 @@ struct arch_irn_ops_if_t { * @param irn The node. * @param offset The offset of the node's stack frame entity. */ - void (*set_frame_offset)(const void *self, ir_node *irn, int offset); + void (*set_frame_offset)(ir_node *irn, int offset); /** * Returns the delta of the stackpointer for nodes that increment or @@ -231,7 +235,7 @@ struct arch_irn_ops_if_t { * @return 0 if the stackpointer is not modified with a constant * value, otherwise the increment/decrement value */ - int (*get_sp_bias)(const void *self, const ir_node *irn); + int (*get_sp_bias)(const ir_node *irn); /** * Returns an inverse operation which yields the i-th argument @@ -244,7 +248,7 @@ struct arch_irn_ops_if_t { * @param obstack The obstack to use for allocation of the returned nodes array * @return The inverse operation or NULL if operation invertible */ - arch_inverse_t *(*get_inverse)(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack); + arch_inverse_t *(*get_inverse)(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack); /** * Get the estimated cycle count for @p irn. @@ -254,7 +258,7 @@ struct arch_irn_ops_if_t { * * @return The estimated cycle count for this operation */ - int (*get_op_estimated_cost)(const void *self, const ir_node *irn); + int (*get_op_estimated_cost)(const ir_node *irn); /** * Asks the backend whether operand @p i of @p irn can be loaded form memory internally @@ -265,7 +269,7 @@ struct arch_irn_ops_if_t { * * @return nonzero if argument can be loaded or zero otherwise */ - int (*possible_memory_operand)(const void *self, const ir_node *irn, unsigned int i); + int (*possible_memory_operand)(const ir_node *irn, unsigned int i); /** * Ask the backend to assimilate @p reload of operand @p i into @p irn. @@ -275,29 +279,7 @@ struct arch_irn_ops_if_t { * @param spill The spill. * @param i The position of the reload. */ - void (*perform_memory_operand)(const void *self, ir_node *irn, ir_node *spill, unsigned int i); -}; - -/** - * irn_ops base class. - */ -struct arch_irn_ops_t { - const arch_irn_ops_if_t *impl; -}; - -/** - * Somebody who can be asked about IR nodes. - */ -struct arch_irn_handler_t { - - /** - * Get the operations of an irn. - * @param self The handler from which the method is invoked. - * @param irn Some node. - * @return Operations for that irn. - */ - const void *(*get_irn_ops)(const arch_irn_handler_t *handler, - const ir_node *irn); + void (*perform_memory_operand)(ir_node *irn, ir_node *spill, unsigned int i); }; /** @@ -311,6 +293,11 @@ struct arch_code_generator_if_t { */ void *(*init)(be_irg_t *birg); + /** + * return node used as base in pic code addresses + */ + ir_node* (*get_pic_base)(void *self); + /** * Called before abi introduce. */ @@ -327,11 +314,6 @@ struct arch_code_generator_if_t { */ void (*spill)(void *self, be_irg_t *birg); - /** - * Called before scheduling. - */ - void (*before_sched)(void *self); - /** * Called before register allocation. */ @@ -374,13 +356,14 @@ do { \ #define arch_code_generator_before_abi(cg) _arch_cg_call(cg, before_abi) #define arch_code_generator_prepare_graph(cg) _arch_cg_call(cg, prepare_graph) -#define arch_code_generator_before_sched(cg) _arch_cg_call(cg, before_sched) #define arch_code_generator_before_ra(cg) _arch_cg_call(cg, before_ra) #define arch_code_generator_after_ra(cg) _arch_cg_call(cg, after_ra) #define arch_code_generator_finish(cg) _arch_cg_call(cg, finish) #define arch_code_generator_done(cg) _arch_cg_call(cg, done) #define arch_code_generator_spill(cg, birg) _arch_cg_call_env(cg, birg, spill) #define arch_code_generator_has_spiller(cg) ((cg)->impl->spill != NULL) +#define arch_code_generator_get_pic_base(cg) \ + ((cg)->impl->get_pic_base != NULL ? (cg)->impl->get_pic_base(cg) : NULL) /** * Code generator base class. @@ -389,21 +372,6 @@ struct arch_code_generator_t { const arch_code_generator_if_t *impl; }; -/** - * ISA base class. - */ -struct arch_isa_t { - const arch_isa_if_t *impl; - const arch_register_t *sp; /** The stack pointer register. */ - const arch_register_t *bp; /** The base pointer register. */ - const int stack_dir; /** -1 for decreasing, 1 for increasing. */ - const be_main_env_t *main_env; /** the be main environment */ -}; - -#define arch_isa_stack_dir(isa) ((isa)->stack_dir) -#define arch_isa_sp(isa) ((isa)->sp) -#define arch_isa_bp(isa) ((isa)->bp) - /** * Architecture interface. */ @@ -411,28 +379,33 @@ struct arch_isa_if_t { /** * Initialize the isa interface. * @param file_handle the file handle to write the output to - * @param main_env the be main environment * @return a new isa instance */ - void *(*init)(FILE *file_handle); + arch_env_t *(*init)(FILE *file_handle); /** * Free the isa instance. */ void (*done)(void *self); + /** + * Called directly after initialization. Backend should handle all + * intrinsics here. + */ + void (*handle_intrinsics)(void); + /** * Get the the number of register classes in the isa. * @return The number of register classes. */ - int (*get_n_reg_class)(const void *self); + unsigned (*get_n_reg_class)(const void *self); /** * Get the i-th register class. * @param i The number of the register class. * @return The register class. */ - const arch_register_class_t *(*get_reg_class)(const void *self, int i); + const arch_register_class_t *(*get_reg_class)(const void *self, unsigned i); /** * Get the register class which shall be used to store a value of a given mode. @@ -445,18 +418,10 @@ struct arch_isa_if_t { /** * Get the ABI restrictions for procedure calls. * @param self The this pointer. - * @param method_type The type of the method (procedure) in question. + * @param call_type The call type of the method (procedure) in question. * @param p The array of parameter locations to be filled. */ - void (*get_call_abi)(const void *self, ir_type *method_type, be_abi_call_t *abi); - - /** - * The irn handler for this architecture. - * The irn handler is registered by the Firm back end - * when the architecture is initialized. - * (May be NULL). - */ - const arch_irn_handler_t *(*get_irn_handler)(const void *self); + void (*get_call_abi)(const void *self, ir_type *call_type, be_abi_call_t *abi); /** * Get the code generator interface. @@ -498,7 +463,8 @@ struct arch_isa_if_t { /** * Returns an 2-dim array of execution units, @p irn can be executed on. - * The first dimension is the type, the second the allowed units of this type. + * The first dimension is the type, the second the allowed units of this + * type. * Each dimension is a NULL terminated list. * @param self The isa object. * @param irn The node. @@ -520,47 +486,87 @@ struct arch_isa_if_t { /** * Return an ordered list of irgs where code should be generated for. - * If NULL is returned, all irg will be taken into account and they will be - * generated in an arbitrary order. + * If NULL is returned, all irg will be taken into account and they will be + * generated in an arbitrary order. * @param self The isa object. - * @param irgs A flexible array ARR_F of length 0 where the backend cann append the desired irgs. + * @param irgs A flexible array ARR_F of length 0 where the backend can append the desired irgs. * @return A flexible array ARR_F containing all desired irgs in the desired order. */ ir_graph **(*get_backend_irg_list)(const void *self, ir_graph ***irgs); -}; -#define arch_isa_get_n_reg_class(isa) ((isa)->impl->get_n_reg_class(isa)) -#define arch_isa_get_reg_class(isa,i) ((isa)->impl->get_reg_class(isa, i)) -#define arch_isa_get_irn_handler(isa) ((isa)->impl->get_irn_handler(isa)) -#define arch_isa_get_call_abi(isa,tp,abi) ((isa)->impl->get_call_abi((isa), (tp), (abi))) -#define arch_isa_get_reg_class_for_mode(isa,mode) ((isa)->impl->get_reg_class_for_mode((isa), (mode))) -#define arch_isa_make_code_generator(isa,irg) ((isa)->impl->make_code_generator((isa), (irg))) -#define arch_isa_get_reg_class_alignment(isa, cls) ((isa)->impl->get_reg_class_alignment((isa), (cls))) -#define arch_isa_get_allowed_execution_units(isa, irn) ((isa)->impl->get_allowed_execution_units((isa), (irn))) -#define arch_isa_get_machine(isa) ((isa)->impl->get_machine((isa))) -#define arch_isa_get_backend_irg_list(isa, irgs) ((isa)->impl->get_backend_irg_list((isa), (irgs))) + /** + * mark node as rematerialized + */ + void (*mark_remat)(const void *self, ir_node *node); + + /** + * parse an assembler constraint part and set flags according to its nature + * advances the *c pointer to point to the last parsed character (so if you + * parse a single character don't advance c) + */ + asm_constraint_flags_t (*parse_asm_constraint)(const void *self, const char **c); -#define ARCH_MAX_HANDLERS 8 + /** + * returns true if the string is a valid clobbered (register) in this + * backend + */ + int (*is_valid_clobber)(const void *self, const char *clobber); +}; + +#define arch_env_done(env) ((env)->impl->done(env)) +#define arch_env_handle_intrinsics(env) \ + do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0) +#define arch_env_get_n_reg_class(env) ((env)->impl->get_n_reg_class(env)) +#define arch_env_get_reg_class(env,i) ((env)->impl->get_reg_class(env, i)) +#define arch_env_get_reg_class_for_mode(env,mode) ((env)->impl->get_reg_class_for_mode((env), (mode))) +#define arch_env_get_call_abi(env,tp,abi) ((env)->impl->get_call_abi((env), (tp), (abi))) +#define arch_env_get_code_generator_if(env) ((env)->impl->get_code_generator_if((env))) +#define arch_env_get_list_sched_selector(env,selector) ((env)->impl->get_list_sched_selector((env), (selector))) +#define arch_env_get_ilp_sched_selector(env) ((env)->impl->get_ilp_sched_selector(env)) +#define arch_env_get_reg_class_alignment(env,cls) ((env)->impl->get_reg_class_alignment((env), (cls))) +#define arch_env_get_params(env) ((env)->impl->get_params()) +#define arch_env_get_allowed_execution_units(env,irn) ((env)->impl->get_allowed_execution_units((env), (irn))) +#define arch_env_get_machine(env) ((env)->impl->get_machine(env)) +#define arch_env_get_backend_irg_list(env,irgs) ((env)->impl->get_backend_irg_list((env), (irgs))) +#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((env), (c)) +#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((env), (clobber)) +#define arch_env_mark_remat(env,node) \ + do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((env), (node)); } while(0) /** - * Environment for the architecture infrastructure. - * Keep this everywhere you're going. + * ISA base class. */ struct arch_env_t { - arch_isa_t *isa; /**< The isa about which everything is. */ + const arch_isa_if_t *impl; + const arch_register_t *sp; /** The stack pointer register. */ + const arch_register_t *bp; /** The base pointer register. */ + const arch_register_class_t *link_class; /** The static link pointer register class. */ + int stack_dir; /** -1 for decreasing, 1 for increasing. */ + int stack_alignment; /** power of 2 stack alignment */ + const be_main_env_t *main_env; /** the be main environment */ + int spill_cost; /** cost for a be_Spill node */ + int reload_cost; /** cost for a be_Reload node */ +}; - arch_irn_handler_t const *handlers[ARCH_MAX_HANDLERS]; /**< The handlers are organized as - a stack. */ +static inline unsigned arch_irn_get_n_outs(const ir_node *node) +{ + backend_info_t *info = be_get_info(node); + return ARR_LEN(info->out_infos); +} - int handlers_tos; /**< The stack pointer of the handler - stack. */ -}; +static inline bool arch_irn_consider_in_reg_alloc( + const arch_register_class_t *cls, const ir_node *node) +{ + const arch_register_req_t *req = arch_get_register_req_out(node); + return + req->cls == cls && + !(req->type & arch_register_req_type_ignore); +} -/** - * Get the isa of an arch environment. - * @param env The environment. - * @return The isa with which the env was initialized with. - */ -#define arch_env_get_isa(env) ((env)->isa) +static inline bool arch_irn_is_ignore(const ir_node *irn) +{ + const arch_register_req_t *req = arch_get_register_req_out(irn); + return !!(req->type & arch_register_req_type_ignore); +} -#endif /* FIRM_BE_BEARCH_T_H */ +#endif