Alias keyword (#868)

Implementation for an "alias" keyword.

By now, only applied inside memory descriptions.

* Make "mem_alias" a separate nonterminal.

The previous implementation attempt caused a syntax error in
yacc code, and separating mem_alias on the same level as
mem_spec appears to be the cleaner solution anyway.

* Maintain real memory aliases.

Instead of duplicating the aliased memory with a new name, maintain a
second list of memory aliases (per device) that contains a pointer to
the memory area it is aliased to. That way, a memory name can be
clearly distinguished between the canonical one and any aliases.

* Check p->mem_alias != NULL before touching it

* Add avr_find_memalias()

This takes a memory region as input, and searches whether an
alias can be found for it.

* We need to add a list structure for the mem_alias list, always.

By that means, mem_alias won't ever be NULL, so no need to check
later.

Also, in avr_dup_part(), duplicate the alias list.

* In a memory alias, actually remember the current name.

* In avr_dup_part(), adjust pointers of aliased memories

While walking the list of memories, for each entry, see if there is an
alias pointing to it. If so, allocate a duplicated one, and fix its
aliased_mem pointer to point to the duplicated memory region instead
of the original one.

* Add avr_locate_mem_noalias()

When looking whether any memory region has already been defined for
the current part while parsing the config file, only non-aliased names
must be considered. Otherwise, a newly defined alias would kick out
the memory definition it is being aliased to.

* When defining a mem_alias, drop any existing one of that name.

* Actually use avr_find_memalias() to find aliases

* Add declaration for avr_find_memalias()

* When defining a memory, also search for an existing alias

If the newly defined name has the same as an existing alias, the alias
can be removed.

Note that we do explicitly *not* remove any memory by the same name of
a later defined alias, as this might invalidate another alias'es
pointer. If someone defines that, the alias name just won't ever be
found by avr_locate_mem().
This commit is contained in:
Jörg Wunsch
2022-02-10 20:39:19 +01:00
committed by GitHub
parent ba314f23e9
commit d134dc8fff
6 changed files with 193 additions and 21 deletions

View File

@@ -68,6 +68,7 @@ static int pin_name;
%token K_PAGE_SIZE
%token K_PAGED
%token K_ALIAS
%token K_BAUDRATE
%token K_BS2
%token K_BUFF
@@ -1238,13 +1239,24 @@ part_parm :
mem_specs
{
AVRMEM * existing_mem;
AVRMEM_ALIAS * existing_alias;
existing_mem = avr_locate_mem(current_part, current_mem->desc);
existing_mem = avr_locate_mem_noalias(current_part, current_mem->desc);
if (existing_mem != NULL) {
lrmv_d(current_part->mem, existing_mem);
avr_free_mem(existing_mem);
}
ladd(current_part->mem, current_mem);
existing_alias = avr_locate_memalias(current_part, current_mem->desc);
if (existing_alias != NULL) {
lrmv_d(current_part->mem_alias, existing_alias);
avr_free_memalias(existing_alias);
}
if (is_alias) {
avr_free_mem(current_mem); // alias mem has been already entered below
is_alias = false;
} else {
ladd(current_part->mem, current_mem);
}
current_mem = NULL;
} |
@@ -1281,6 +1293,7 @@ yesno :
mem_specs :
mem_spec TKN_SEMI |
mem_alias TKN_SEMI |
mem_specs mem_spec TKN_SEMI
;
@@ -1410,6 +1423,44 @@ mem_spec :
}
;
mem_alias :
K_ALIAS TKN_STRING
{
AVRMEM * existing_mem;
existing_mem = avr_locate_mem(current_part, $2->value.string);
if (existing_mem == NULL) {
yyerror("%s alias to non-existent memory %s",
current_mem->desc, $2->value.string);
free_token($2);
YYABORT;
}
// if this alias does already exist, drop the old one
AVRMEM_ALIAS * alias = avr_locate_memalias(current_part, current_mem->desc);
if (alias) {
lrmv_d(current_part->mem_alias, alias);
avr_free_memalias(alias);
}
// NB: we do *not* check whether any non-alias region of the
// same name does already exist, as that one could be pointed to
// by an(other) alias as well. If we destroyed it, the alias
// pointer would get stale. In case someone defines the same
// name both as a regular memory as well as an alias, the
// regular one will always be found first by avr_locate_mem().
is_alias = true;
alias = avr_new_memalias();
// alias->desc and current_mem->desc have the same length
// definition, thus no need to check for length here
strcpy(alias->desc, current_mem->desc);
alias->aliased_mem = existing_mem;
ladd(current_part->mem_alias, alias);
free_token($2);
}
;
%%