Commit 1c3051b8 authored by Matthias Braun's avatar Matthias Braun
Browse files

add support for alias entities

parent 0f2adc23
......@@ -198,6 +198,33 @@ FIRM_API ir_entity *new_entity(ir_type *owner, ident *name, ir_type *tp);
FIRM_API ir_entity *new_parameter_entity(ir_type *owner, size_t pos,
ir_type *type);
/**
* Creates a new entity aliasing another entity.
* An aliasing entity is a logically separate entity with its own name,
* but instead of having a definition the linker will merge the name with
* the definition of the aliased entity.
* In gcc this feature is known as __attribute__((alias())).
*
* @param owner owning type (must be a global segment)
* @param name name of the entity
* @param alias entity that is aliased
* @param type type of the aliased entity, should but need not be the same
* type as the one of the aliased entity
* @return the newly created entity
*/
FIRM_API ir_entity *new_alias_entity(ir_type *owner, ident *name,
ir_entity *alias, ir_type *type);
/**
* Sets the entity an alias entity aliases.
*/
FIRM_API void set_entity_alias(ir_entity *alias, ir_entity *aliased);
/**
* Returns the entity aliased by an alias entity.
*/
FIRM_API ir_entity *get_entity_alias(const ir_entity *alias);
/**
* Check an entity. Currently, we check only if initialized constants
* are build on the const irg graph.
......
......@@ -405,7 +405,7 @@ static be_gas_section_t determine_basic_section(const ir_entity *entity)
return GAS_SECTION_RODATA;
}
if (entity_is_null(entity))
if (entity_is_null(entity) && get_entity_kind(entity) != IR_ENTITY_ALIAS)
return GAS_SECTION_BSS;
return GAS_SECTION_DATA;
......@@ -1265,6 +1265,20 @@ static void emit_indirect_symbol(const ir_entity *entity,
}
}
static void emit_alias(const ir_entity *entity)
{
/* no support on other object file formats (yet) */
if (be_gas_object_file_format != OBJECT_FILE_FORMAT_ELF)
panic("alias entities only supported for ELF");
be_emit_cstring("\t.set ");
be_gas_emit_entity(entity);
be_emit_char(',');
be_gas_emit_entity(get_entity_alias(entity));
be_emit_char('\n');
be_emit_write_line();
}
char const *be_gas_get_private_prefix(void)
{
return be_gas_object_file_format == OBJECT_FILE_FORMAT_MACH_O ? "L" : ".L";
......@@ -1343,15 +1357,17 @@ void be_gas_begin_block(const ir_node *block, bool needs_label)
*/
static void emit_global(be_gas_decl_env_t *env, const ir_entity *entity)
{
ir_entity_kind kind = get_entity_kind(entity);
/* Block labels are already emitted in the code. */
ir_type *type = get_entity_type(entity);
if (type == get_code_type())
if (kind == IR_ENTITY_LABEL)
return;
/* we already emitted all methods with graphs in other functions like
* be_gas_emit_function_prolog(). All others don't need to be emitted. */
be_gas_section_t section = determine_section(env, entity);
if (is_Method_type(type) && section != GAS_SECTION_PIC_TRAMPOLINES) {
if (kind == IR_ENTITY_METHOD && section != GAS_SECTION_PIC_TRAMPOLINES) {
return;
}
......@@ -1376,16 +1392,15 @@ static void emit_global(be_gas_decl_env_t *env, const ir_entity *entity)
emit_visibility(entity);
unsigned alignment = get_effective_entity_alignment(entity);
if (!is_po2(alignment))
panic("alignment not a power of 2");
emit_section(section, entity);
if (section == GAS_SECTION_PIC_TRAMPOLINES
|| section == GAS_SECTION_PIC_SYMBOLS) {
|| section == GAS_SECTION_PIC_SYMBOLS) {
emit_indirect_symbol(entity, section);
return;
} else if (get_entity_kind(entity) == IR_ENTITY_ALIAS) {
emit_alias(entity);
return;
}
/* nothing left to do without an initializer */
......@@ -1393,6 +1408,9 @@ static void emit_global(be_gas_decl_env_t *env, const ir_entity *entity)
return;
/* alignment */
unsigned alignment = get_effective_entity_alignment(entity);
if (!is_po2(alignment))
panic("alignment not a power of 2");
if (alignment > 1) {
emit_align(alignment);
}
......
......@@ -96,6 +96,7 @@ typedef enum keyword_t {
kw_float_mode,
kw_int_mode,
kw_irg,
kw_alias,
kw_label,
kw_method,
kw_modes,
......@@ -211,6 +212,7 @@ static void symtbl_init(void)
INSERT(tt_throws, "throw", true);
INSERT(tt_throws, "nothrow", false);
INSERTKEYWORD(alias);
INSERTKEYWORD(asm);
INSERTKEYWORD(compound_member);
INSERTKEYWORD(constirg);
......@@ -693,6 +695,7 @@ static void write_entity(write_env_t *env, ir_entity *ent)
fputc('\t', env->file);
switch ((ir_entity_kind)ent->entity_kind) {
case IR_ENTITY_ALIAS: write_symbol(env, "alias"); break;
case IR_ENTITY_NORMAL: write_symbol(env, "entity"); break;
case IR_ENTITY_METHOD: write_symbol(env, "method"); break;
case IR_ENTITY_LABEL: write_symbol(env, "label"); break;
......@@ -736,6 +739,9 @@ static void write_entity(write_env_t *env, ir_entity *ent)
write_volatility(env, get_entity_volatility(ent));
switch ((ir_entity_kind)ent->entity_kind) {
case IR_ENTITY_ALIAS:
write_entity_ref(env, get_entity_alias(ent));
break;
case IR_ENTITY_NORMAL:
if (ent->initializer != NULL) {
write_symbol(env, "initializer");
......@@ -1832,6 +1838,11 @@ static void read_entity(read_env_t *env, ir_entity_kind kind)
volatility = read_volatility(env);
switch (kind) {
case IR_ENTITY_ALIAS: {
ir_entity *aliased = read_entity_ref(env);
entity = new_alias_entity(owner, name, aliased, type);
break;
}
case IR_ENTITY_NORMAL:
entity = new_entity(owner, name, type);
if (ld_name != NULL)
......@@ -1923,6 +1934,9 @@ static void read_typegraph(read_env_t *env)
case kw_entity:
read_entity(env, IR_ENTITY_NORMAL);
break;
case kw_alias:
read_entity(env, IR_ENTITY_ALIAS);
break;
case kw_label:
read_entity(env, IR_ENTITY_LABEL);
break;
......
......@@ -115,6 +115,27 @@ ir_entity *new_label_entity(ir_label_t label)
return res;
}
ir_entity *new_alias_entity(ir_type *owner, ident *name, ir_entity *aliased,
ir_type *type)
{
ir_entity *res = intern_new_entity(owner, IR_ENTITY_ALIAS, name, type);
res->attr.alias.aliased = aliased;
hook_new_entity(res);
return res;
}
void set_entity_alias(ir_entity *entity, ir_entity *aliased)
{
assert(get_entity_kind(entity) == IR_ENTITY_ALIAS);
entity->attr.alias.aliased = aliased;
}
ir_entity *get_entity_alias(const ir_entity *entity)
{
assert(get_entity_kind(entity) == IR_ENTITY_ALIAS);
return entity->attr.alias.aliased;
}
/**
* Free entity attributes.
*/
......@@ -868,15 +889,21 @@ int entity_is_externally_visible(const ir_entity *entity)
int entity_has_definition(const ir_entity *entity)
{
switch (entity->entity_kind) {
switch (get_entity_kind(entity)) {
case IR_ENTITY_METHOD:
return get_entity_irg(entity) != NULL
&& (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN) == 0;
case IR_ENTITY_NORMAL:
return entity->initializer != NULL;
case IR_ENTITY_LABEL:
case IR_ENTITY_ALIAS:
return true;
default:
return entity->initializer != NULL;
case IR_ENTITY_PARAMETER:
case IR_ENTITY_UNKNOWN:
case IR_ENTITY_COMPOUND_MEMBER:
return false;
}
panic("invalid entity kind");
}
void ir_init_entity(ir_prog *irp)
......
......@@ -135,12 +135,18 @@ typedef struct parameter_ent_attr {
lowering...) */
} parameter_ent_attr;
typedef struct alias_ent_attr {
mtp_additional_properties properties;
ir_entity *aliased;
} alias_ent_attr;
typedef enum ir_entity_kind {
IR_ENTITY_NORMAL,
IR_ENTITY_METHOD,
IR_ENTITY_ALIAS,
IR_ENTITY_COMPOUND_MEMBER,
IR_ENTITY_PARAMETER,
IR_ENTITY_LABEL,
IR_ENTITY_METHOD,
IR_ENTITY_NORMAL,
IR_ENTITY_PARAMETER,
IR_ENTITY_UNKNOWN,
} ir_entity_kind;
......@@ -193,6 +199,8 @@ struct ir_entity {
compound_member_ent_attr compound_member;
/** parameter number for parameter entities */
parameter_ent_attr parameter;
/** alias attributes */
alias_ent_attr alias;
} attr; /**< type specific attributes */
};
......
......@@ -263,6 +263,17 @@ int check_entity(const ir_entity *entity)
const ir_type *owner = get_entity_owner(entity);
switch (get_entity_kind(entity)) {
case IR_ENTITY_ALIAS:
if (!is_segment_type(owner)) {
report_error("alias entity %+F has non-segment owner %+F", entity,
owner);
fine = false;
}
if (initializer != NULL) {
report_error("alias entity %+F has initializer", entity);
fine = false;
}
break;
case IR_ENTITY_NORMAL:
if (!is_data_type(type)) {
report_error("normal entity %+F has non-data type %+F", entity,
......
......@@ -108,9 +108,24 @@ static void do_type_walk(type_or_ent tore,
cont.typ = get_entity_type(ent);
do_type_walk(cont, pre, post, env);
/* walk over the value types */
if (ent->initializer != NULL) {
walk_initializer(ent->initializer, pre, post, env);
switch (get_entity_kind(ent)) {
case IR_ENTITY_ALIAS:
cont.ent = get_entity_alias(ent);
if (cont.ent != NULL)
do_type_walk(cont, pre, post, env);
break;
case IR_ENTITY_METHOD:
case IR_ENTITY_NORMAL:
/* walk over the value types */
if (ent->initializer != NULL) {
walk_initializer(ent->initializer, pre, post, env);
}
break;
case IR_ENTITY_UNKNOWN:
case IR_ENTITY_PARAMETER:
case IR_ENTITY_LABEL:
case IR_ENTITY_COMPOUND_MEMBER:
break;
}
break;
case k_type:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment