X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Fcgana.c;h=a1cf2240c9cb44f50c625759f1bcaf71d690e931;hb=00894f1e0b6e74ca6c12d253dd30f7d873808977;hp=dd06f0c971039794f382481e64d1b00befa205f7;hpb=36332e717eebd9b98603a99ea24e390a1d2aa3be;p=libfirm diff --git a/ir/ana/cgana.c b/ir/ana/cgana.c index dd06f0c97..a1cf2240c 100644 --- a/ir/ana/cgana.c +++ b/ir/ana/cgana.c @@ -50,6 +50,7 @@ #include "ircons.h" #include "irgmod.h" #include "iropt.h" +#include "irtools.h" #include "irflag_t.h" #include "dbginfo_t.h" @@ -84,12 +85,12 @@ static eset *entities = NULL; /** Returns the entity that contains the implementation of the inherited * entity if available, else returns the entity passed. */ static ir_entity *get_inherited_methods_implementation(ir_entity *inh_meth) { - assert(get_atomic_ent_value(inh_meth) && "constant entity without value"); - assert((get_irn_op(get_atomic_ent_value(inh_meth)) == op_SymConst) && - (get_SymConst_kind(get_atomic_ent_value(inh_meth)) == symconst_addr_ent) && + ir_node *value = get_atomic_ent_value(inh_meth); + assert(value && "constant entity without value"); + assert(is_SymConst_addr_ent(value) && "Complex constant values not supported -- address of method should be straight constant!"); - return get_SymConst_entity(get_atomic_ent_value(inh_meth)); + return get_SymConst_entity(value); } /** Collect the entity representing the implementation of this @@ -191,8 +192,10 @@ static void sel_methods_walker(ir_node *node, void *env) { /* Call standard optimizations */ if (is_Sel(node)) { ir_node *new_node = optimize_in_place(node); - if (node != new_node) + if (node != new_node) { exchange(node, new_node); + node = new_node; + } } /* replace SymConst(name)-operations by SymConst(ent) */ @@ -205,44 +208,44 @@ static void sel_methods_walker(ir_node *node, void *env) { } } } else if (is_Sel(node) && is_Method_type(get_entity_type(get_Sel_entity(node)))) { - ir_entity *ent = get_SymConst_entity(get_atomic_ent_value(get_Sel_entity(node))); - assert(get_entity_peculiarity(ent) != peculiarity_inherited); - - if (!eset_contains(entities, ent)) { - /* Entity not yet handled. Find all (internal or external) - * implemented methods that overwrites this entity. - * This set is stored in the entity link. */ - set_entity_link(ent, get_impl_methods(ent)); - eset_insert(entities, ent); - } + ir_entity *ent = get_SymConst_entity(get_atomic_ent_value(get_Sel_entity(node))); + assert(get_entity_peculiarity(ent) != peculiarity_inherited); + + if (!eset_contains(entities, ent)) { + /* Entity not yet handled. Find all (internal or external) + * implemented methods that overwrites this entity. + * This set is stored in the entity link. */ + set_entity_link(ent, get_impl_methods(ent)); + eset_insert(entities, ent); + } - /* -- As an add on we get an optimization that removes polymorphic calls. - This optimization is more powerful than that in transform_node_Sel(). -- */ - arr = get_entity_link(ent); - if (arr == NULL) { - /* - * The Sel node never returns a pointer to a usable method. - * We could not call it, but it may be description: - * We call a method in a dead part of the program. - */ - assert(get_entity_peculiarity(ent) == peculiarity_description); - } - else if (get_opt_closed_world() && get_opt_dyn_meth_dispatch() && - (ARR_LEN(arr) == 1 && arr[0] != NULL)) { - ir_node *new_node; - - /* - * The Sel node returns only one possible method. - * So we could replace the Sel node by a SymConst. - * This method must exists. - */ - set_irg_current_block(current_ir_graph, get_nodes_block(node)); - assert(get_entity_peculiarity(get_SymConst_entity(get_atomic_ent_value(arr[0]))) == - peculiarity_existent); - new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(arr[0])); - DBG_OPT_POLY(node, new_node); - exchange(node, new_node); - } + /* -- As an add on we get an optimization that removes polymorphic calls. + This optimization is more powerful than that in transform_node_Sel(). -- */ + arr = get_entity_link(ent); + if (arr == NULL) { + /* + * The Sel node never returns a pointer to a usable method. + * We could not call it, but it may be description: + * We call a method in a dead part of the program. + */ + assert(get_entity_peculiarity(ent) == peculiarity_description); + } + else if (get_opt_closed_world() && get_opt_dyn_meth_dispatch() && + (ARR_LEN(arr) == 1 && arr[0] != NULL)) { + ir_node *new_node; + + /* + * The Sel node returns only one possible method. + * So we could replace the Sel node by a SymConst. + * This method must exists. + */ + set_irg_current_block(current_ir_graph, get_nodes_block(node)); + assert(get_entity_peculiarity(get_SymConst_entity(get_atomic_ent_value(arr[0]))) == + peculiarity_existent); + new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(arr[0])); + DBG_OPT_POLY(node, new_node); + exchange(node, new_node); + } } } @@ -345,7 +348,7 @@ static void free_mark_proj(ir_node * node, long n, eset * set) { * op_Tuple oder ein Knoten, der in "free_ana_walker" behandelt * wird. */ ir_node * pred = get_Proj_pred(node); - if (get_irn_link(pred) != MARK && get_irn_op(pred) == op_Tuple) { + if (get_irn_link(pred) != MARK && is_Tuple(pred)) { free_mark_proj(get_Tuple_pred(pred, get_Proj_proj(node)), n, set); } else { /* nothing: da in "free_ana_walker" behandelt. */ @@ -372,7 +375,7 @@ static void free_mark_proj(ir_node * node, long n, eset * set) { assert(0 && "unexpected opcode or opcode not implemented"); break; } - set_irn_link(node, NULL); + // set_irn_link(node, NULL); } /** @@ -428,7 +431,6 @@ static void free_mark(ir_node *node, eset * set) { /* nothing: */ break; } - set_irn_link(node, NULL); } /** @@ -476,15 +478,28 @@ static void free_ana_walker(ir_node *node, void *env) { } break; } - set_irn_link(node, NULL); } -static void add_method_address_intitialzer(ir_initializer_t *initializer, - eset *set) +/** + * Add all method addresses in global new style initializers to the set. + * + * @note + * We do NOT check the type here, just it it's an entity address. + * The reason for this is code like: + * + * void *p = function; + * + * which is sometimes used to anchor functions. + */ +static void add_method_address_inititializer(ir_initializer_t *initializer, + eset *set) { - switch(initializer->kind) { - case IR_INITIALIZER_CONST: { - ir_node *n = initializer->consti.value; + ir_node *n; + size_t i; + + switch (initializer->kind) { + case IR_INITIALIZER_CONST: + n = initializer->consti.value; /* let's check if it's the address of a function */ if (is_Global(n)) { @@ -494,21 +509,17 @@ static void add_method_address_intitialzer(ir_initializer_t *initializer, eset_insert(set, ent); } return; - } case IR_INITIALIZER_TARVAL: case IR_INITIALIZER_NULL: return; - case IR_INITIALIZER_COMPOUND: { - size_t i; - - for(i = 0; i < initializer->compound.n_initializers; ++i) { + case IR_INITIALIZER_COMPOUND: + for (i = 0; i < initializer->compound.n_initializers; ++i) { ir_initializer_t *sub_initializer = initializer->compound.initializers[i]; - add_method_address_intitialzer(sub_initializer, set); + add_method_address_inititializer(sub_initializer, set); } return; } - } panic("invalid initializer found"); } @@ -534,7 +545,7 @@ static void add_method_address(ir_entity *ent, eset *set) return; if (ent->has_initializer) { - + add_method_address_inititializer(get_entity_initializer(ent), set); } else if (is_atomic_entity(ent)) { tp = get_entity_type(ent); @@ -587,18 +598,19 @@ static ir_entity **get_free_methods(int *length) for (i = get_irp_n_irgs() - 1; i >= 0; --i) { irg = get_irp_irg(i); ent = get_irg_entity(irg); - /* insert "external visible" methods. */ if (get_entity_visibility(ent) != visibility_local) { + /* insert non-local (external) methods. */ eset_insert(free_set, ent); - } - /* insert "sticky" methods. */ - if (get_entity_stickyness(ent) == stickyness_sticky) { + } else if (get_entity_stickyness(ent) == stickyness_sticky) { + /* insert "sticky" methods. */ eset_insert(free_set, ent); } - /* Find all method entities that gets "visible" trough this graphs, + ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK); + /* Find all method entities that gets "visible" through this graphs, * for instance because their address is stored. */ - irg_walk_graph(irg, NULL, free_ana_walker, free_set); + irg_walk_graph(irg, firm_clear_link, free_ana_walker, free_set); + ir_free_resources(irg, IR_RESOURCE_IRN_LINK); } /* insert all methods that are used in global variables initializers */ @@ -620,7 +632,7 @@ static ir_entity **get_free_methods(int *length) /* Finally, transform the set into an array. */ *length = eset_count(free_set); - arr = xmalloc(sizeof(ir_entity *) * (*length)); + arr = XMALLOCN(ir_entity*, *length); for (i = 0, ent = eset_first(free_set); ent; ent = eset_next(free_set)) { arr[i++] = ent; } @@ -667,8 +679,6 @@ static void callee_ana_proj(ir_node *node, long n, eset *methods) { eset_insert(methods, unknown_entity); /* free method -> unknown */ break; } - - set_irn_link(node, NULL); } /** @@ -732,13 +742,6 @@ static void callee_ana_node(ir_node *node, eset *methods) { callee_ana_node(get_Mux_true(node), methods); break; - case iro_Psi: - for (i = get_Psi_n_conds(node) - 1; i >= 0; --i) { - callee_ana_node(get_Psi_val(node, i), methods); - } - callee_ana_node(get_Psi_default(node), methods); - break; - case iro_Id: callee_ana_node(get_Id_pred(node), methods); break; @@ -758,8 +761,6 @@ static void callee_ana_node(ir_node *node, eset *methods) { assert(0 && "invalid opcode or opcode not implemented"); break; } - - set_irn_link(node, NULL); } /**