*/
ir_type *get_tls_type(void);
+/**
+ * returns the constructors type containing entities that should be put in
+ * the constructos section. (The constructors section contains pointers to
+ * module constructor functions)
+ */
+ir_type *get_constructors_type(void);
+
/** Adds type to the list of types in irp. */
void add_irp_type(ir_type *typ);
#define IS_WRITTEN(a) ((a) & ptr_access_write)
#define IS_STORED(a) ((a) & ptr_access_store)
-/**
- * Supported image sections.
- * Currently only methods can be placed in different sections.
- */
-typedef enum {
- section_text, /**< The code segment. This is the default for methods. */
- section_constructors /**< The constructor section. */
-} ir_img_section;
-
-/** Returns the section of a method. */
-ir_img_section get_method_img_section(const ir_entity *method);
-
-/** Sets the section of a method. */
-void set_method_img_section(ir_entity *method, ir_img_section section);
-
-
/**
* @page tyop type operations
* This module specifies the kinds of types available in firm.
*/
typedef struct _be_gas_decl_env {
const be_main_env_t *main_env; /**< The main backend environment, used for it's debug handle. */
- int dump_tls;
- waitq *worklist; /**< A worklist we use to place not yet handled entities on. */
+ be_gas_section_t section;
+ waitq *worklist; /**< A worklist we use to place not yet handled entities on. */
} be_gas_decl_env_t;
/************************************************************************/
*
* @param env the gas output environment
* @param ent the entity to be dumped
- * @param emit_commons if non-zero, emit commons (non-local uninitialized entities)
*/
-static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons)
+static void dump_global(be_gas_decl_env_t *env, ir_entity *ent)
{
ir_type *type = get_entity_type(ent);
ident *ld_ident = get_entity_ld_ident(ent);
unsigned align = get_type_alignment_bytes(type);
int emit_as_common = 0;
- be_gas_section_t section;
- ir_variability variability;
- ir_visibility visibility;
-
- if (is_Method_type(type)) {
- if (be_gas_flavour != GAS_FLAVOUR_MACH_O
- && get_method_img_section(ent) == section_constructors) {
- be_gas_emit_switch_section(GAS_SECTION_CTOR);
- emit_align(align);
- dump_size_type(align);
- be_emit_ident(ld_ident);
- be_emit_char('\n');
- be_emit_write_line();
- }
+ be_gas_section_t section = env->section;
+ ir_variability variability = get_entity_variability(ent);
+ ir_visibility visibility = get_entity_visibility(ent);
- return;
- }
-
- variability = get_entity_variability(ent);
- visibility = get_entity_visibility(ent);
- section = GAS_SECTION_DATA;
- if (env->dump_tls) {
- section = GAS_SECTION_TLS;
+ if (section != (be_gas_section_t) -1) {
emit_as_common = 0;
} else if (variability == variability_constant) {
/* a constant entity, put it on the rdata */
} else if (variability == variability_uninitialized) {
/* uninitialized entity put it in bss segment */
section = GAS_SECTION_COMMON;
- if (emit_commons && visibility != visibility_local)
+ if (visibility != visibility_local)
emit_as_common = 1;
}
*
* @param gt a global like type, either the global or the TLS one
* @param env an environment
- * @param emit_commons if non-zero, emit commons (non-local uninitialized entities)
* @param only_emit_marked if non-zero, external allocated entities that do not have
* its visited flag set are ignored
*/
static void be_gas_dump_globals(ir_type *gt, be_gas_decl_env_t *env,
- int emit_commons, int only_emit_marked)
+ int only_emit_marked)
{
int i, n = get_compound_n_members(gt);
waitq *worklist = new_waitq();
while (!waitq_empty(worklist)) {
ir_entity *ent = waitq_get(worklist);
- dump_global(env, ent, emit_commons);
+ dump_global(env, ent);
}
del_waitq(worklist);
env.main_env = main_env;
/* dump global type */
- be_gas_dump_globals(get_glob_type(), &env, 1, only_emit_marked_entities);
-
- /* dump the Thread Local Storage */
- env.dump_tls = 1;
- be_gas_dump_globals(get_tls_type(), &env, 0, only_emit_marked_entities);
- env.dump_tls = 0;
+ env.section = (be_gas_section_t) -1;
+ be_gas_dump_globals(get_glob_type(), &env, only_emit_marked_entities);
+ env.section = GAS_SECTION_TLS;
+ be_gas_dump_globals(get_tls_type(), &env, only_emit_marked_entities);
+ env.section = GAS_SECTION_CTOR;
+ be_gas_dump_globals(get_constructors_type(), &env,
+ only_emit_marked_entities);
}
set_Load_mem(get_irn_link(get_irn_link(bb)), mem);
}
+static void add_constructor(ir_entity *method)
+{
+ ir_type *method_type = get_entity_type(method);
+ ident *id = id_unique("constructor_ptrt.%u");
+ ir_type *ptr_type = new_type_pointer(id, method_type, mode_P_code);
+
+ ir_type *constructors = get_constructors_type();
+ ident *ide = id_unique("constructor_ptr.%u");
+ ir_entity *ptr = new_entity(constructors, ide, ptr_type);
+ ir_graph *irg = get_const_code_irg();
+ ir_node *val = new_rd_SymConst_addr_ent(NULL, irg, mode_P_code,
+ method, NULL);
+
+ set_entity_compiler_generated(ptr, 1);
+ set_atomic_ent_value(ptr, val);
+}
/**
* Generates a new irg which calls the initializer
irg_finalize_cons(irg);
+ add_constructor(ent);
+
return irg;
}
#define GLOBAL_TYPE_NAME "GlobalType"
/** The name of the Thread Local Storage type. */
#define TLS_TYPE_NAME "TLS"
+/** The name of the constructors type. */
+#define CONSTRUCTORS_TYPE_NAME "Constructors"
/** The initial name of the irp program. */
#define INITAL_PROG_NAME "no_name_set"
static ir_prog *complete_ir_prog(ir_prog *irp) {
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
- irp->name = IDENT(INITAL_PROG_NAME);
- irp->glob_type = new_type_class(IDENT(GLOBAL_TYPE_NAME));
- irp->tls_type = new_type_struct(IDENT(TLS_TYPE_NAME));
+ irp->name = IDENT(INITAL_PROG_NAME);
+ irp->glob_type = new_type_class(IDENT(GLOBAL_TYPE_NAME));
+ irp->tls_type = new_type_struct(IDENT(TLS_TYPE_NAME));
+ irp->constructors_type = new_type_struct(IDENT(CONSTRUCTORS_TYPE_NAME));
/* Remove these types from type list. Must be treated differently than
other types. */
remove_irp_type(irp->glob_type);
remove_irp_type(irp->tls_type);
+ remove_irp_type(irp->constructors_type);
/* Set these flags for debugging. */
irp->glob_type->flags |= tf_global_type;
/* frees all memory used by irp. Types in type list, irgs in irg
list and entities in global type must be freed by hand before. */
void free_ir_prog(void) {
- if (irp->glob_type)
- free_type(irp->glob_type);
- if (irp->tls_type)
- free_type(irp->tls_type);
+ free_type(irp->glob_type);
+ free_type(irp->tls_type);
+ free_type(irp->constructors_type);
/* @@@ * free_ir_graph(irp->const_code_irg); * ?? End has no in?? */
DEL_ARR_F(irp->graphs);
return _get_tls_type();
}
+ir_type *(get_constructors_type)(void) {
+ return _get_constructors_type();
+}
+
/* Adds irg to the list of ir graphs in irp. */
void add_irp_irg(ir_graph *irg) {
assert(irg != NULL);
return irp->tls_type = skip_tid(irp->tls_type);
}
+static INLINE ir_type *
+_get_constructors_type(void) {
+ assert(irp);
+ return irp->constructors_type = skip_tid(irp->constructors_type);
+}
+
static INLINE int
_get_irp_n_irgs(void) {
assert (irp && irp->graphs);
#define get_const_code_irg() _get_const_code_irg()
#define get_glob_type() _get_glob_type()
#define get_tls_type() _get_tls_type()
+#define get_constructors_type() _get_constructors_type()
#define get_irp_next_region_nr() _get_irp_next_region_nr()
#define get_irp_next_label_nr() _get_irp_next_label_nr()
have fields and procedures. */
ir_type *tls_type; /**< The thread local storage type. Must be a struct as it can
only have fields. */
+ ir_type *constructors_type; /**< contains links to module constructor
+ functions. Must be a struct */
ir_type **types; /**< A list of all types in the ir. */
ir_mode **modes; /**< A list of all modes in the ir. */
ir_op **opcodes; /**< A list of all opcodes in the ir. */
res->attr.mtd_attr.param_access = NULL;
res->attr.mtd_attr.param_weight = NULL;
res->attr.mtd_attr.irg = NULL;
- res->attr.mtd_attr.section = section_text;
} else if (is_compound_type(type)) {
res->variability = variability_uninitialized;
res->value = NULL;
ent->attr.mtd_attr.vtable_number = vtable_number;
} /* set_entity_vtable_number */
-/* Returns the section of a method. */
-ir_img_section get_method_img_section(const ir_entity *ent) {
- assert(is_method_entity((ir_entity *)ent));
- return ent->attr.mtd_attr.section;
-} /* get_method_img_section */
-
-/* Sets the section of a method. */
-void set_method_img_section(ir_entity *ent, ir_img_section section) {
- assert(is_method_entity(ent));
- ent->attr.mtd_attr.section = section;
-} /* set_method_img_section */
-
int
(is_entity)(const void *thing) {
return _is_entity(thing);
ptr_access_kind *param_access; /**< the parameter access */
float *param_weight; /**< The weight of method's parameters. Parameters
with a high weight are good for procedure cloning. */
- ir_img_section section; /**< The code section where this method should be placed */
} method_ent_attr;