/* * Transform Sel[method] to SymC[method] if possible. * (see opt_polymorphy in libfirm) */ static ir_node *transform_node_Sel2(ir_node *node) { ir_node *new_node; ir_entity *ent = get_Sel_entity(node); if (get_irp_phase_state() == phase_building) return node; if (!get_opt_dyn_meth_dispatch()) return node; if (!is_Method_type(get_entity_type(ent))) return node; ddispatch_binding bind = oo_get_entity_binding(ent); assert (bind != bind_unknown); if (bind == bind_static) return node; /* If we know the dynamic type, we can replace the Sel by a constant. */ ir_node *ptr = get_Sel_ptr(node); /* The address we select from. */ ir_type *dyn_tp = get_irn_typeinfo_type(ptr); if (dyn_tp != initial_type) { ir_entity *called_ent; /* We know which method will be called, no dispatch necessary. */ called_ent = resolve_ent_polymorphy(dyn_tp, ent); assert (! oo_get_method_is_abstract(called_ent)); assert (! oo_get_class_is_interface(get_entity_owner(called_ent))); new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(called_ent), get_nodes_block(node)); return new_node; } return node; }
int check_entity(const ir_entity *entity) { bool fine = true; ir_type *tp = get_entity_type(entity); ir_linkage linkage = get_entity_linkage(entity); fine &= constants_on_wrong_irg(entity); if (is_method_entity(entity)) { ir_graph *irg = get_entity_irg(entity); if (irg != NULL) { ir_entity *irg_entity = get_irg_entity(irg); if (irg_entity != entity) { report_error("entity(%+F)->irg->entity(%+F) relation invalid", entity, irg_entity); fine = false; } } if (get_entity_peculiarity(entity) == peculiarity_existent) { ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity)); if (impl == NULL) { report_error("inherited method entity %+F must have constant pointing to existent entity.", entity); fine = false; } } } if (linkage & IR_LINKAGE_NO_CODEGEN) { if (!is_method_entity(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity); fine = false; } else if (get_entity_irg(entity) == NULL) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity); fine = false; } if (get_entity_visibility(entity) != ir_visibility_external) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity); fine = false; } } check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK"); check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT, "GARBAGE_COLLECT"); check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE"); if (is_atomic_entity(entity) && entity->initializer != NULL) { ir_mode *mode = NULL; ir_initializer_t *initializer = entity->initializer; switch (initializer->kind) { case IR_INITIALIZER_CONST: mode = get_irn_mode(get_initializer_const_value(initializer)); break; case IR_INITIALIZER_TARVAL: mode = get_tarval_mode(get_initializer_tarval_value(initializer)); break; case IR_INITIALIZER_NULL: case IR_INITIALIZER_COMPOUND: break; } if (mode != NULL && mode != get_type_mode(tp)) { report_error("initializer of entity %+F has wrong mode.", entity); fine = false; } } return fine; }