* @see ir_type, ir_entity
*/
+/**
+ * Visibility classed for entities.
+ */
+typedef enum {
+ /**
+ * The entity is visible outside the compilation unit, but it is defined
+ * here.
+ */
+ ir_visibility_default,
+ /**
+ * The entity is local to the compilation unit.
+ * A local entity is not visible in other compilation units.
+ * Note that the entity might still be accessed indirectly from other units
+ * through pointers.
+ */
+ ir_visibility_local,
+ /**
+ * The entity is defined outside the compilation unit but potentially used
+ * here.
+ */
+ ir_visibility_external
+} ir_visibility;
+
/**
* linkage specifies how the linker treats symbols
*/
typedef enum {
- IR_LINKAGE_DEFAULT = 0,
+ IR_LINKAGE_DEFAULT = 0,
/**
* A symbol whose definition won't change in a program.
* Optimisation might replace loads from this entity with constants.
* Also most linkers put such data in a constant segment which is shared
* between multiple running instances of the same application.
*/
- IR_LINKAGE_CONSTANT = 1 << 0,
+ IR_LINKAGE_CONSTANT = 1 << 0,
/**
* The entity is a weak symbol.
* A weak symbol is overridden by a non-weak symbol if one exists.
* Most linkers only support the IR_LINKAGE_WEAK in combination with
* IR_LINKAGE_MERGE.
*/
- IR_LINKAGE_WEAK = 1 << 1,
- /**
- * The entity is local to the compilation unit.
- * A local entity will not be exported by the linker and is not visible
- * in other compilation units. Note that the entity might still be accessed
- * indirectly from other units through pointers.
- */
- IR_LINKAGE_LOCAL = 1 << 2,
- /**
- * The entity is defined in another compilation.
- */
- IR_LINKAGE_EXTERN = 1 << 3,
+ IR_LINKAGE_WEAK = 1 << 1,
/**
* The entity may be removed when it isn't referenced anywhere in the
* compilation unit even if it is exported (non-local).
* Typically used for C++ instantiated template code (,,COMDAT'' section).
*/
- IR_LINKAGE_GARBAGE_COLLECT = 1 << 5,
+ IR_LINKAGE_GARBAGE_COLLECT = 1 << 2,
/**
* The linker will try to merge entities with same name from different
* compilation units. This is the usual behaviour for global variables
* without explicit initialisation in C (``COMMON'' symbols). It's also
* typically used in C++ for instantiated template code (,,COMDAT'' section)
*/
- IR_LINKAGE_MERGE = 1 << 6,
+ IR_LINKAGE_MERGE = 1 << 3,
/**
* Some entity uses are potentially hidden from the compiler.
* (For example because they happen in an asm("") statement. This flag
* read/write behaviour to global variables or changing calling conventions
* from cdecl to fastcall.
*/
- IR_LINKAGE_HIDDEN_USER = 1 << 7,
+ IR_LINKAGE_HIDDEN_USER = 1 << 4
} ir_linkage;
/**
};
/**
- * Return 1 if the entity is visible outside the current compilation unit.
- * (The entity might still be accessible indirectly through pointers)
- * This is a convenience function and does the same as
- * (get_entity_linkage(entity) & IR_LINKAGE_LOCAL) == 0
+ * Return the visibility class of an entity
*/
-int entity_is_externally_visible(const ir_entity *entity);
+ir_visibility get_entity_visibility(const ir_entity *entity);
/**
- * Return 1 if the entity has a definition (initializer) in the current
- * compilation unit
+ * Set visibility class of an entity
*/
-int entity_has_definition(const ir_entity *entity);
+void set_entity_visibility(ir_entity *entity, ir_visibility visibility);
/**
- * Return 1 if the entity is/will be defined in the current compilation unit.
- * This is a convenience function for
- * (get_entity_linkage(entity) & IR_LINKAGE_EXTERN) == 0.
- *
- * In contrast to entity_has_definition(entity) you have no guarantee here that
- * the entity actually has a firm initializer.
+ * Return 1 if the entity is visible outside the current compilation unit
+ * or to unknown callers (like asm statements).
+ * (The entity might still be accessible indirectly through pointers)
+ * This is a convenience function and does the same as
+ * get_entity_visibility(entity) != ir_visibility_local ||
+ * (get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER)
*/
-int entity_is_defined_here(const ir_entity *entity);
+int entity_is_externally_visible(const ir_entity *entity);
/**
- * Return 1 if the entity is constant. Constant means the entities value
- * won't change at all when the program is running.
+ * Return 1 if the entity has a definition (initializer) in the current
+ * compilation unit
*/
-int entity_is_constant(const ir_entity *entity);
+int entity_has_definition(const ir_entity *entity);
/**
* Creates a new entity.
*/
void types_calc_finalization(void);
-/**
- * @deprecated
- */
-typedef enum {
- visibility_local,
- visibility_external_visible,
- visibility_external_allocated
-} ir_visibility;
-
/** @deprecated */
ir_visibility get_type_visibility(const ir_type *tp);
/** @deprecated */
ent = get_irg_entity(irg);
linkage = get_entity_linkage(ent);
- if (!(linkage & IR_LINKAGE_LOCAL)
+ if (entity_is_externally_visible(ent)
|| (linkage & IR_LINKAGE_HIDDEN_USER)) {
eset_insert(free_set, ent);
}
ir_entity *ent = get_compound_member(tp, i);
ir_entity_usage flags = ir_usage_none;
- if (! (get_entity_linkage(ent) & IR_LINKAGE_LOCAL)) {
+ if (entity_is_externally_visible(ent)) {
flags |= ir_usage_unknown;
}
set_entity_usage(ent, flags);
ir_graph *irg = get_irp_irg(i);
ir_entity *ent = get_irg_entity(irg);
ir_entity_usage flags = get_entity_usage(ent);
- ir_linkage linkage = get_entity_linkage(ent);
- if ((linkage & IR_LINKAGE_LOCAL) &&
- !(linkage & IR_LINKAGE_HIDDEN_USER) &&
+ if (!entity_is_externally_visible(ent) &&
!(flags & ir_usage_address_taken)) {
ir_type *mtp = get_entity_type(ent);
ir_entity *ent = get_irg_entity(graph);
ir_linkage linkage = get_entity_linkage(ent);
- if (!(linkage & IR_LINKAGE_LOCAL)
+ if (entity_is_externally_visible(ent)
|| (linkage & IR_LINKAGE_HIDDEN_USER)) {
eset_insert(_live_graphs, graph);
}
rt_iDiv.exc_mem_proj_nr = pn_Div_M;
rt_iDiv.res_proj_nr = pn_Div_res;
- set_entity_linkage(rt_iDiv.ent, IR_LINKAGE_EXTERN | IR_LINKAGE_CONSTANT);
+ add_entity_linkage(rt_iDiv.ent, IR_LINKAGE_CONSTANT);
+ set_entity_visibility(rt_iDiv.ent, ir_visibility_external);
map_Div->kind = INTRINSIC_INSTR;
map_Div->op = op_Div;
rt_uDiv.exc_mem_proj_nr = pn_Div_M;
rt_uDiv.res_proj_nr = pn_Div_res;
- set_entity_linkage(rt_uDiv.ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(rt_uDiv.ent, ir_visibility_external);
map_Div->kind = INTRINSIC_INSTR;
map_Div->op = op_Div;
rt_iMod.exc_mem_proj_nr = pn_Mod_M;
rt_iMod.res_proj_nr = pn_Mod_res;
- set_entity_linkage(rt_iMod.ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(rt_iMod.ent, ir_visibility_external);
map_Mod->kind = INTRINSIC_INSTR;
map_Mod->op = op_Mod;
rt_uMod.exc_mem_proj_nr = pn_Mod_M;
rt_uMod.res_proj_nr = pn_Mod_res;
- set_entity_linkage(rt_uMod.ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(rt_uMod.ent, ir_visibility_external);
map_Mod->kind = INTRINSIC_INSTR;
map_Mod->op = op_Mod;
ir_type *parent = be->pic_trampolines_type;
ir_entity *ent = new_entity(parent, old_id, type);
set_entity_ld_ident(ent, id);
- set_entity_linkage(ent, IR_LINKAGE_LOCAL);
+ set_entity_visibility(ent, ir_visibility_local);
return ent;
}
ir_type *parent = be->pic_symbols_type;
ir_entity *ent = new_entity(parent, old_id, type);
set_entity_ld_ident(ent, id);
- set_entity_linkage(ent, IR_LINKAGE_LOCAL);
+ set_entity_visibility(ent, ir_visibility_local);
return ent;
}
*/
static int can_address_relative(ir_entity *entity)
{
- return !(get_entity_linkage(entity) & IR_LINKAGE_EXTERN);
+ return get_entity_visibility(entity) != ir_visibility_external;
}
/** patches SymConsts to work in position independent code */
static void emit_entity_visibility(const ir_entity *entity)
{
- ir_linkage linkage = get_entity_linkage(entity);
+ ir_visibility visibility = get_entity_visibility(entity);
+ ir_linkage linkage = get_entity_linkage(entity);
- if (! (linkage & IR_LINKAGE_LOCAL)) {
+ if (visibility != ir_visibility_local) {
be_emit_cstring(".globl ");
be_emit_ident(get_entity_ld_ident(entity));
be_emit_char('\n');
be_emit_cstring("\t.def\t");
be_emit_string(name);
be_emit_cstring(";");
- if (get_entity_linkage(entity) & IR_LINKAGE_LOCAL) {
+ if (get_entity_visibility(entity) == ir_visibility_local) {
be_emit_cstring("\t.scl\t3;");
} else {
be_emit_cstring("\t.scl\t2;");
ident *ld_ident = get_entity_ld_ident(ent);
unsigned alignment = get_effective_entity_alignment(ent);
be_gas_section_t section = determine_section(env, ent);
- ir_linkage linkage = get_entity_linkage(ent);
/* we already emitted all methods. Except for the trampolines which
* the assembler/linker generates */
be_dbg_variable(ent);
/* nothing to do for externally defined values */
- if (linkage & IR_LINKAGE_EXTERN)
+ if (get_entity_visibility(ent) == ir_visibility_external)
return;
if (!is_po2(alignment))
if (section == GAS_SECTION_BSS &&
(get_entity_linkage(ent) & IR_LINKAGE_MERGE)) {
- if (get_entity_linkage(ent) & (IR_LINKAGE_LOCAL|IR_LINKAGE_EXTERN)) {
+ if (get_entity_visibility(ent) != ir_visibility_default) {
panic("merge link semantic not supported for local/extern entities");
}
emit_common(ent);
type_num = get_type_number(h, rtp);
be_emit_irprintf("\t.stabs\t\"%s:%c%u\",%u,0,0,%s\n",
get_entity_name(ent),
- entity_is_externally_visible(ent) ? 'F' : 'f',
+ get_entity_visibility(ent) == ir_visibility_local ? 'f' : 'F',
type_num,
N_FUN,
get_entity_ld_name(ent));
unsigned tp_num = get_type_number(h, get_entity_type(ent));
char buf[1024];
- if (entity_is_externally_visible(ent)) {
- /* a global variable */
- snprintf(buf, sizeof(buf), "\t.stabs\t\"%s:G%u\",%d,0,0,0\n",
- get_entity_name(ent), tp_num, N_GSYM);
- } else {
+ if (get_entity_visibility(ent) == ir_visibility_local) {
/* some kind of local */
ir_linkage linkage = get_entity_linkage(ent);
int kind = N_STSYM;
kind = N_ROSYM;
snprintf(buf, sizeof(buf), "\t.stabs\t\"%s:S%u\",%d,0,0,%s\n",
get_entity_name(ent), tp_num, kind, get_entity_ld_name(ent));
+ } else {
+ /* a global variable */
+ snprintf(buf, sizeof(buf), "\t.stabs\t\"%s:G%u\",%d,0,0,0\n",
+ get_entity_name(ent), tp_num, N_GSYM);
}
buf[sizeof(buf) - 1] = '\0';
mcount = new_entity(get_glob_type(), ID("mcount"), tp);
/* FIXME: enter the right ld_ident here */
set_entity_ld_ident(mcount, get_entity_ident(mcount));
- set_entity_linkage(mcount, IR_LINKAGE_EXTERN);
+ set_entity_visibility(mcount, ir_visibility_external);
}
instrument_initcall(cg->irg, mcount);
}
res = new_entity(get_glob_type(), ia32_unique_id(".LC%u"), tp);
set_entity_ld_ident(res, get_entity_ident(res));
- set_entity_linkage(res, IR_LINKAGE_LOCAL | IR_LINKAGE_CONSTANT);
+ set_entity_visibility(res, ir_visibility_local);
+ add_entity_linkage(res, IR_LINKAGE_CONSTANT);
/* we create a new entity here: It's initialization must resist on the
const code irg */
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_linkage(entity) & IR_LINKAGE_EXTERN) {
+ if (get_entity_visibility(entity) == ir_visibility_external) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
be_gas_emit_entity(entity);
if (get_entity_owner(entity) == get_tls_type()) {
- if (get_entity_linkage(entity) & IR_LINKAGE_EXTERN) {
+ if (get_entity_visibility(entity) == ir_visibility_external) {
be_emit_cstring("@INDNTPOFF");
} else {
be_emit_cstring("@NTPOFF");
tv = new_tarval_from_long(value, mode);
ent = new_entity(glob, new_id_from_str(name), type);
set_entity_ld_ident(ent, get_entity_ident(ent));
- set_entity_linkage(ent, IR_LINKAGE_LOCAL | IR_LINKAGE_CONSTANT);
+ set_entity_visibility(ent, ir_visibility_local);
+ add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
cnst_irg = get_const_code_irg();
cnst = new_r_Const(cnst_irg, tv);
if (ent == NULL) {
/* create library entity */
ent = env->divdi3 = new_entity(get_glob_type(), ID("__divdi3"), method);
- set_entity_linkage(ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(ent, ir_visibility_external);
set_entity_ld_ident(ent, ID("__divdi3"));
}
} else {
if (ent == NULL) {
/* create library entity */
ent = env->udivdi3 = new_entity(get_glob_type(), ID("__udivdi3"), method);
- set_entity_linkage(ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(ent, ir_visibility_external);
set_entity_ld_ident(ent, ID("__udivdi3"));
}
}
if (ent == NULL) {
/* create library entity */
ent = env->moddi3 = new_entity(get_glob_type(), ID("__moddi3"), method);
- set_entity_linkage(ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(ent, ir_visibility_external);
set_entity_ld_ident(ent, ID("__moddi3"));
}
} else {
if (ent == NULL) {
/* create library entity */
ent = env->umoddi3 = new_entity(get_glob_type(), ID("__umoddi3"), method);
- set_entity_linkage(ent, IR_LINKAGE_EXTERN);
+ set_entity_visibility(ent, ir_visibility_external);
set_entity_ld_ident(ent, ID("__umoddi3"));
}
}
ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);
set_entity_ld_ident(ent, get_entity_ident(ent));
- set_entity_linkage(ent, IR_LINKAGE_LOCAL | IR_LINKAGE_CONSTANT);
+ add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
+ set_entity_visibility(ent, ir_visibility_local);
if (kct == ia32_ULLBIAS) {
ir_initializer_t *initializer = create_initializer_compound(2);
ent = new_entity(get_glob_type(), ia32_unique_id(".LC%u"), tp);
set_entity_ld_ident(ent, get_entity_ident(ent));
- set_entity_linkage(ent, IR_LINKAGE_LOCAL | IR_LINKAGE_CONSTANT);
+ set_entity_visibility(ent, ir_visibility_local);
+ add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
initializer = create_initializer_compound(2);
ent = new_entity(get_glob_type(), new_id_from_str(buf), tp);
set_entity_ld_ident(ent, get_entity_ident(ent));
- set_entity_linkage(ent, IR_LINKAGE_CONSTANT|IR_LINKAGE_LOCAL);
+ set_entity_visibility(ent, ir_visibility_local);
+ add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
/* we create a new entity here: It's initialization must resist on the
const code irg */
fprintf(F, " constant");
if (linkage & IR_LINKAGE_WEAK)
fprintf(F, " weak");
- if (linkage & IR_LINKAGE_LOCAL)
- fprintf(F, " local");
- if (linkage & IR_LINKAGE_EXTERN)
- fprintf(F, " extern");
if (linkage & IR_LINKAGE_GARBAGE_COLLECT)
fprintf(F, " garbage_collect");
if (linkage & IR_LINKAGE_MERGE)
tt_type_state,
tt_volatility,
tt_linkage,
- tt_segment
+ tt_segment,
+ tt_visibility
} typetag_t;
typedef enum keyword_t
INSERT(tt_linkage, "constant", IR_LINKAGE_CONSTANT);
INSERT(tt_linkage, "weak", IR_LINKAGE_WEAK);
- INSERT(tt_linkage, "local", IR_LINKAGE_LOCAL);
- INSERT(tt_linkage, "extern", IR_LINKAGE_EXTERN);
INSERT(tt_linkage, "garbage_collect", IR_LINKAGE_GARBAGE_COLLECT);
INSERT(tt_linkage, "merge", IR_LINKAGE_MERGE);
INSERT(tt_linkage, "hidden_user", IR_LINKAGE_HIDDEN_USER);
+ INSERT(tt_visibility, "local", ir_visibility_local);
+ INSERT(tt_visibility, "external", ir_visibility_external);
+ INSERT(tt_visibility, "default", ir_visibility_default);
+
INSERTKEYWORD(constirg);
INSERTKEYWORD(entity);
INSERTKEYWORD(irg);
case tt_tpo: return "type";
case tt_type_state: return "type state";
case tt_volatility: return "volatility";
+ case tt_visibility: return "visibility";
}
return "<UNKNOWN>";
}
glob = get_glob_type();
entity = new_entity(glob, id_unique("block_%u"), get_code_type());
- set_entity_linkage(entity, IR_LINKAGE_LOCAL|IR_LINKAGE_CONSTANT);
+ set_entity_visibility(entity, ir_visibility_local);
+ set_entity_linkage(entity, IR_LINKAGE_CONSTANT);
nr = get_irp_next_label_nr();
set_entity_label(entity, nr);
set_entity_compiler_generated(entity, 1);
value = NULL;
/* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr);
- if (ent != NULL && !(get_entity_linkage(ent) & IR_LINKAGE_EXTERN)) {
- /* a static allocation that is not external: there should be NO exception
- * when loading even if we cannot replace the load itself. */
+ if (ent != NULL
+ && get_entity_visibility(ent) != ir_visibility_external) {
+ /* a static allocation that is not external: there should be NO
+ * exception when loading even if we cannot replace the load itself.
+ */
/* no exception, clear the info field as it might be checked later again */
if (info->projs[pn_Load_X_except]) {
callee_env = get_irg_link(callee);
if (callee_env->n_callers == 1 &&
callee != current_ir_graph &&
- (get_entity_linkage(ent) & IR_LINKAGE_LOCAL)) {
+ !entity_is_externally_visible(ent)) {
weight += 700;
}
/* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr);
- if (ent != NULL && !(get_entity_linkage(ent) & IR_LINKAGE_EXTERN)) {
+ if (ent != NULL && get_entity_visibility(ent) != ir_visibility_external) {
/* a static allocation that is not external: there should be NO exception
* when loading even if we cannot replace the load itself. */
ir_node *value = NULL;
new_entity = copy_entity_name(q->ent, clone_ident);
/* a cloned entity is always local */
- add_entity_linkage(new_entity, IR_LINKAGE_LOCAL);
+ set_entity_visibility(new_entity, ir_visibility_local);
/* set a ld name here: Should we mangle this ? */
set_entity_ld_ident(new_entity, get_entity_ident(new_entity));
res->aligned = align_is_aligned;
res->usage = ir_usage_unknown;
res->compiler_gen = 0;
+ res->visibility = ir_visibility_default;
res->offset = -1;
res->offset_bit_remainder = 0;
res->alignment = 0;
return ent->attr.code_attr.label;
}
-static void verify_linkage(ir_entity *entity)
+static void verify_visibility(const ir_entity *entity)
{
- ir_linkage linkage = entity->linkage;
- /* local and extern are mutually exclusive */
- (void) linkage;
- assert(! ((linkage & IR_LINKAGE_EXTERN) && (linkage & IR_LINKAGE_LOCAL)));
- if (!is_method_entity(entity) && (linkage & IR_LINKAGE_EXTERN)) {
+ if (get_entity_visibility(entity) == ir_visibility_external
+ && !is_method_entity(entity)) {
assert(!entity_has_definition(entity));
}
+}
+
+void set_entity_visibility(ir_entity *entity, ir_visibility visibility)
+{
+ entity->visibility = visibility;
+ verify_visibility(entity);
+}
+
+ir_visibility get_entity_visibility(const ir_entity *entity)
+{
+ return entity->visibility;
+}
+
+static void verify_linkage(const ir_entity *entity)
+{
+ ir_linkage linkage = entity->linkage;
+ /* weak symbols can't really be constant, since someone else can always
+ * exchange them */
assert(! ((linkage & IR_LINKAGE_CONSTANT) && (linkage & IR_LINKAGE_WEAK)));
}
int entity_is_externally_visible(const ir_entity *entity)
{
- return (get_entity_linkage(entity) & IR_LINKAGE_LOCAL) == 0;
+ return get_entity_visibility(entity) != ir_visibility_local
+ || (get_entity_linkage(entity) & IR_LINKAGE_HIDDEN_USER);
}
int entity_has_definition(const ir_entity *entity)
assert(!unknown_entity && "Call firm_init_entity() only once!");
unknown_entity = new_rd_entity(NULL, firm_unknown_type, new_id_from_str(UNKNOWN_ENTITY_NAME), firm_unknown_type);
- set_entity_linkage(unknown_entity, IR_LINKAGE_EXTERN);
+ set_entity_visibility(unknown_entity, ir_visibility_external);
set_entity_ld_ident(unknown_entity, get_entity_ident(unknown_entity));
res->kind = k_type;
res->type_op = type_op;
res->mode = mode;
- res->visibility = visibility_external_allocated;
+ res->visibility = ir_visibility_external;
res->flags = tf_none;
res->size = 0;
res->align = 0;