X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbearch.h;h=4b0d187e4559eeabfe96f86e37e11a5f9cbece87;hb=662fc44c951bdb45a9b7d9563e9ffbb87101b9e4;hp=568d90c79905bb4c1635d530a61f55e03992e4cc;hpb=0b7c02c299246820d8ccdea4e9b4e21774fc90fc;p=libfirm diff --git a/ir/be/bearch.h b/ir/be/bearch.h index 568d90c79..4b0d187e4 100644 --- a/ir/be/bearch.h +++ b/ir/be/bearch.h @@ -1,274 +1,290 @@ +/* + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. + * + * This file is part of libFirm. + * + * This file may be distributed and/or modified under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation and appearing in the file LICENSE.GPL included in the + * packaging of this file. + * + * Licensees holding valid libFirm Professional Edition licenses may use + * this file in accordance with the libFirm Commercial License. + * Agreement provided with the Software. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ -#ifndef _FIRM_BEARCH_H -#define _FIRM_BEARCH_H - -#include "firm_config.h" - -#include "irop_t.h" -#include "irnode_t.h" -#include "irmode_t.h" +/** + * @file + * @brief Processor architecture specification. + * @author Sebastian Hack + * @version $Id$ + */ +#ifndef FIRM_BE_BEARCH_H +#define FIRM_BE_BEARCH_H + +#include "firm_types.h" +#include "bitset.h" +#include "be.h" +#include "obst.h" + +typedef struct arch_register_class_t arch_register_class_t; +typedef struct arch_register_req_t arch_register_req_t; +typedef struct arch_register_t arch_register_t; +typedef struct arch_flag_t arch_flag_t; +typedef struct arch_inverse_t arch_inverse_t; +typedef struct arch_isa_if_t arch_isa_if_t; +typedef struct arch_env_t arch_env_t; +typedef struct arch_code_generator_t arch_code_generator_t; +typedef struct arch_code_generator_if_t arch_code_generator_if_t; + +typedef enum arch_register_class_flags_t { + arch_register_class_flag_none = 0, + arch_register_class_flag_manual_ra = 1, /**< don't do automatic register allocation for this class */ + arch_register_class_flag_state = 2 +} arch_register_class_flags_t; + +typedef enum arch_register_type_t { + arch_register_type_none = 0, + arch_register_type_caller_save = 1, /**< The register must be saved by the caller + upon a function call. It thus can be overwritten + in the called function. */ + arch_register_type_callee_save = 2, /**< The register must be saved by the caller + upon a function call. It thus can be overwritten + in the called function. */ + arch_register_type_ignore = 4, /**< Do not consider this register when allocating. */ + arch_register_type_joker = 8, /**< The emitter can choose an arbitrary register */ + arch_register_type_virtual = 16, /**< This is just a virtual register.Virtual registers have + nearly no constraints, it is a allowed to have multiple + definition for the same register at a point) */ + arch_register_type_state = 32, /**< The register represents a state that should be handled by + bestate code */ +} arch_register_type_t; -#include "hashptr.h" -#include "fourcc.h" -#include "set.h" -#include "list.h" -#include "ident.h" +/** + * Put all registers in a class into a bitset. + * @param cls The class. + * @param bs The bitset. May be NULL. + * @return The number of registers in the class. + */ +extern int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs); + +typedef enum arch_operand_type_t { + arch_operand_type_invalid, + arch_operand_type_memory, + arch_operand_type_register, + arch_operand_type_immediate, + arch_operand_type_symconst, + arch_operand_type_last +} arch_operand_type_t; -#include "bearch.h" +/** + * Different types of register allocation requirements. + */ +typedef enum arch_register_req_type_t { + arch_register_req_type_none = 0, /**< No register requirement. */ + arch_register_req_type_normal = 1, /**< All registers in the class are allowed. */ + arch_register_req_type_limited = 2, /**< Only a real subset of the class is allowed. */ + arch_register_req_type_should_be_same = 4, /**< The register should be equal to another one at the node. */ + arch_register_req_type_must_be_different = 8, /**< The register must be unequal from some other at the node. */ +} arch_register_req_type_t; -#define ARCH_OBJ(name,x) typedef struct _arch_ ## name ## _t arch_ ## name ## _t; -#include "bearch_obj.def" -#undef ARCH_OBJ +extern const arch_register_req_t *arch_no_register_req; -struct _bitset_t; +/** + * Format a register requirements information into a string. + * @param buf The string where to put it to. + * @param len The size of @p buf. + * @param req The requirements structure to format. + * @return A pointer to buf. + */ +extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req, const ir_node *node); -typedef enum _arch_register_type_t { - arch_register_type_none = 0, - arch_register_type_write_invariant, - arch_register_type_caller_saved, /**< The register must be saved by the caller - upon a function call. It thus can be overwritten - in the called function. */ - arch_register_type_callee_saved, /**< The register must be saved by the called function, - it thus survives a function call. */ - arch_register_type_ignore /**< Do not consider this register when allocating. */ -} arch_register_type_t; +/** + * Certain node classes which are relevant for the register allocator. + */ +typedef enum arch_irn_class_t { + arch_irn_class_normal = 1 << 0, + arch_irn_class_spill = 1 << 1, + arch_irn_class_reload = 1 << 2, + arch_irn_class_copy = 1 << 3, + arch_irn_class_perm = 1 << 4, + arch_irn_class_branch = 1 << 5, + arch_irn_class_call = 1 << 6, + arch_irn_class_load = 1 << 7, + arch_irn_class_store = 1 << 8, + arch_irn_class_stackparam = 1 << 9, +} arch_irn_class_t; /** - * A register. + * Some flags describing a node in more detail. */ -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. */ - arch_register_type_t type; /**< The type of the register. */ -}; - -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) -{ - return reg->index; -} - -#define arch_register_get_class(reg) _arch_register_get_class(reg) -#define arch_register_get_index(reg) _arch_register_get_index(reg) +typedef enum arch_irn_flags_t { + arch_irn_flags_none = 0, /**< Node flags. */ + arch_irn_flags_dont_spill = 1, /**< This must not be spilled. */ + arch_irn_flags_rematerializable = 2, /**< This can be replicated instead of spilled/reloaded. */ + arch_irn_flags_ignore = 4, /**< Ignore node during register allocation. */ + arch_irn_flags_modify_sp = 8, /**< I modify the stack pointer. */ + arch_irn_flags_modify_flags = 16, /**< I modify flags. */ + arch_irn_flags_last = arch_irn_flags_modify_flags +} arch_irn_flags_t; /** - * A (sub-) set of registers. + * Get the string representation of a flag. + * This functions does not handle or'ed bitmasks of flags. + * @param flag The flag. + * @return The flag as a string. */ -struct _arch_register_set_t { - const struct _arch_register_class_t *reg_class; /**< The register class for this set. */ - int *regs; /**< An array containing 0/1 at place i - whether the register with index i is - in the set or not. */ -}; +extern const char *arch_irn_flag_str(arch_irn_flags_t flag); -static INLINE int _arch_register_in_set(const arch_register_set_t *set, - const arch_register_t *reg) -{ - if(reg->reg_class != set->reg_class) - return 0; +extern const arch_irn_ops_t *arch_get_irn_ops(const arch_env_t *env, + const ir_node *irn); - return set->regs[reg->index]; -} +extern void arch_set_frame_offset(const arch_env_t *env, ir_node *irn, int bias); +extern ir_entity *arch_get_frame_entity(const arch_env_t *env, const ir_node *irn); +extern void arch_set_frame_entity(const arch_env_t *env, ir_node *irn, ir_entity *ent); +extern int arch_get_sp_bias(const arch_env_t *env, ir_node *irn); + +extern int arch_get_op_estimated_cost(const arch_env_t *env, const ir_node *irn); +extern arch_inverse_t *arch_get_inverse(const arch_env_t *env, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack); +extern int arch_possible_memory_operand(const arch_env_t *env, const ir_node *irn, unsigned int i); +extern void arch_perform_memory_operand(const arch_env_t *env, ir_node *irn, ir_node *spill, unsigned int i); /** - * A class of registers. - * Like general purpose or floating point. + * Get the register requirements for a node. + * @param env The architecture environment. + * @param irn The node. + * @param pos The position of the operand you're interested in. + * @return A pointer to the register requirements. If NULL is returned, the + * operand was no register operand. */ -struct _arch_register_class_t { - const char *name; /**< The name of the register. */ - arch_register_set_t *set; /**< A register set containing all registers - in this class. */ - int n_regs; /**< Number of registers in this class. */ - const arch_register_t *regs; /**< The array of registers. */ -}; - -#define arch_register_class_n_regs(cls) ((cls)->n_regs) - -static INLINE const arch_register_t * -_arch_register_for_index(const arch_register_class_t *cls, int idx) -{ - assert(0 <= idx && idx < cls->n_regs); - return &cls->regs[idx]; -} - -#define arch_register_for_index(cls, idx) \ - _arch_register_for_index(cls, idx) +extern const arch_register_req_t * +arch_get_register_req(const arch_env_t *env, const ir_node *irn, int pos); /** - * Get the register set for a register class. - * @param cls The register class. - * @return The set containing all registers in the class. + * Check if an operand is a register operand. + * @param env The environment. + * @param irn The node. + * @param pos The position of the operand. + * @return 1, if the operand is significant for register allocation, 0 + * if not. */ -#define arch_get_register_set_for_class(cls) ((cls)->set) +extern int arch_is_register_operand(const arch_env_t *env, + const ir_node *irn, int pos); /** - * An immediate. + * Get the number of allocatable registers concerning + * a register class for an operand of a node. + * @param env The environment. + * @param irn The node. + * @param pos The postition of the node's operand. + * @param bs The bitset all allocatable registers shall be put into. + * Note, that you can also pass NULL here. If you don't, + * make sure, the bitset is as large as the register class + * has registers. + * @return The amount of registers allocatable for that operand. */ -struct _arch_immediate_t { - const char *name; /**< The name of the immediate. */ - ir_mode *mode; /**< The mode of the immediate. */ -}; +extern int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn, int pos, bitset_t *bs); /** - * The member of an enum. + * Put all registers which shall not be ignored by the register + * allocator in a bit set. + * @param env The arch env. + * @param cls The register class to consider. + * @param bs The bit set to put the registers to. */ -struct _arch_enum_member_t { - arch_enum_t *enm; /**< The enum, this member belongs to. */ -}; +extern void arch_put_non_ignore_regs(const arch_env_t *env, const arch_register_class_t *cls, bitset_t *bs); /** - * An enumeration operand type. - * - * Enumeration operand types can be used to describe the variants - * of an instruction, like giving the cases for a compare (gt, lt, - * eq, ...) some other special attributes of an instruction. + * Check, if a register is assignable to an operand of a node. + * @param env The architecture environment. + * @param irn The node. + * @param pos The position of the operand. + * @param reg The register. + * @return 1, if the register might be allocated to the operand 0 if not. */ -struct _arch_enum_t { - int n_members; /**< The number of members in this enum. */ - arch_enum_member_t *members[1]; /**< The array of members. */ -}; - -typedef enum _arch_operand_type_t { -#define ARCH_OPERAND_TYPE(name,size_in_irn) arch_operand_type_ ## name, -#include "bearch_operand_types.def" -#undef ARCH_OPERAND_TYPE - arch_operand_type_last -} arch_operand_type_t; - - +extern int arch_reg_is_allocatable(const arch_env_t *env, + const ir_node *irn, int pos, const arch_register_t *reg); /** - * The data for the different flavours of operand types. + * Get the register class of an operand of a node. + * @param env The architecture environment. + * @param irn The node. + * @param pos The position of the operand, -1 for the output. + * @return The register class of the operand or NULL, if + * operand is a non-register operand. */ -typedef union _arch_operand_data_t { - const arch_register_set_t *set; /**< The set of valid registers is directly - given. Note, that if an insn has no constraints, - the set comprises all registers in the - register class. */ +extern const arch_register_class_t * +arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos); - const arch_immediate_t *imm; /**< If the operand is an immediate - operand, this describes the kind of - immediate. */ - - const arch_enum_t *enm; /**< Some enumeration value. */ - - int same_as_pos; /**< 'Same as' position for equals. */ -} arch_operand_data_t; +/** + * Get the register allocated at a certain output operand of a node. + * @param env The arch environment. + * @param irn The node. + * @return The register allocated for this operand + */ +extern const arch_register_t * +arch_get_irn_register(const arch_env_t *env, const ir_node *irn); /** - * An operand to an instruction. + * Set the register for a certain output operand. + * @param env The architecture environment. + * @param irn The node. + * @param reg The register. */ -struct _arch_operand_t { - arch_operand_type_t type; /**< The type of the operand. */ - arch_operand_data_t data; /**< The payload. */ -}; +extern void arch_set_irn_register(const arch_env_t *env, ir_node *irn, + const arch_register_t *reg); /** - * An instruction format. + * Classify a node. + * @param env The architecture environment. + * @param irn The node. + * @return A classification of the node. */ -struct _arch_insn_format_t { - int n_in; /**< Number of in operands. */ - int n_out; /**< Number of out operands. */ +extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn); - arch_operand_t * const *in_operands; /**< In operands. */ - arch_operand_t * const *out_operands; /**< Out operands. */ -}; +#define arch_irn_class_is(env, irn, irn_class) ((arch_irn_classify(env, irn) & arch_irn_class_ ## irn_class) != 0) /** - * An instruction. + * Get the flags of a node. + * @param env The architecture environment. + * @param irn The node. + * @return The flags. */ -struct _arch_insn_t { - const arch_insn_format_t *format; /**< The format of the instruction. */ - ir_op *op; /**< The firm opcode for this insn. */ -}; +extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn); -#define arch_insn_is_allocatable(insn,reg) \ - ((irn)->get_allocatable_regs(irn, cls, NULL) != 0) +#define arch_irn_is(env, irn, flag) ((arch_irn_get_flags(env, irn) & arch_irn_flags_ ## flag) != 0) + +#define arch_irn_has_reg_class(env, irn, pos, cls) \ + ((cls) == arch_get_irn_reg_class(env, irn, pos)) + +#define arch_irn_consider_in_reg_alloc(env, cls, irn) \ + (arch_irn_has_reg_class(env, irn, -1, cls) && !arch_irn_is(env, irn, ignore)) /** - * Architecture interface. + * 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. */ -struct _arch_isa_if_t { - - /** - * Initialize the isa interface. - */ - void (*init)(void); - - /** - * Get the the number of register classes in the isa. - * @return The number of register classes. - */ - int (*get_n_reg_class)(void); - - /** - * 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)(int i); - - /** - * Put all registers of a given class which are allocatable to a - * certain node into a bitset. - * The bitset contains the indices of the registers concerning - * the register class @p cls. - * @param irn The node. - * @param cls The register class. - * @param bs The bitset. Can be NULL. - * @return The number of registers which are allocatable at this node. - */ - int (*get_allocatable_regs)(const ir_node *irn, - const arch_register_class_t *cls, struct _bitset_t *bs); - - int (*is_reg_allocatable)(const ir_node *irn, const arch_register_t *reg); - - /** - * Get the register class, the value of a node belongs to. - * @param irn The node. - * @return The register class of the registers which can hold the - * value of irn. If the node does not return a value, or possesses no - * suitable register class, NULL is returned. - */ - const arch_register_class_t *(*get_irn_reg_class)(const ir_node *irn); - - - - /** - * Get an op for a name. - * @note This method may not be implemented. - * @param name The name of the op. - * @return The op with that name. - */ - ir_op *(*get_op_by_name)(const char *name); -}; +typedef const void *(arch_get_irn_ops_t)(const ir_node *irn); /** - * Check, if the value of a node can be stored in a - * specific register class. - * @param isa The isa. - * @param irn The node. - * @param cls The register class. - * @return 1, if the value can be stored in the register class, 0 if - * not. + * Initialize the architecture environment struct. + * @param isa The isa which shall be put into the environment. + * @param file_handle The file handle + * @return The environment. */ -#define arch_isa_irn_has_reg_class(isa, irn, cls) \ - ((isa)->get_irn_reg_class(irn) == (cls)) +extern arch_env_t *arch_env_init(const arch_isa_if_t *isa, + FILE *file_handle, be_main_env_t *main_env); /** - * Check, if a register is allocatable for an irn. - * @param irn The node. - * @param reg The register. - * @return 1, if the register can be allocated to this node, 0 if not. + * Register an instruction set architecture */ -#define arch_isa_reg_is_allocatable(irn, reg) \ - ((isa)->is_reg_allocatable(irn, reg)) +void be_register_isa_if(const char *name, const arch_isa_if_t *isa); -#endif /* _FIRM_BEARCH_H */ +#endif /* FIRM_BE_BEARCH_H */