summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/instruction-int.h31
-rw-r--r--src/arch/instruction.c296
-rw-r--r--src/arch/instruction.h35
3 files changed, 111 insertions, 251 deletions
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index beb6b50..b7bd5f3 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -60,22 +60,13 @@ struct _GArchInstruction
/**
* Il existe le besoin indéniable d'un verrou pour les accès aux instructions
* liées. Il faut par ailleurs un verrou distinct pour les sources et les
- * destination car une même instruction peut boucler sur elle même et la
+ * destinations car une même instruction peut boucler sur elle même et la
* fonction g_arch_instruction_change_link() pose des verrous sur les
* deux extrémités.
*
- * Par ailleurs, la consommation mémoire augmente vite : GRWLock pèse 16
- * octets et size_t mesure la taille d'un long sur 64 bits.
- *
- * Que ce soit avec les pointeurs (un allocateur aligne généralement les
- * adresses retournées) ou avec les tailles (il est peu probable d'avoir
- * 0x80000000 instructions d'origine), on dispose d'espace mémoire inutilisé
- * adapté pour compresser la structure GArchInstruction.
- *
- * La GLib propose incidemment des fonctions g_bit_lock() / g_bit_unlock()...
- *
- * On perd au passage la distinction entre les accès en lecture et ceux en
- * écriture, mais tant pis : la réduction de l'empreinte mémoire prime !
+ * La GLib propose les fonctions g_bit_lock() / g_bit_unlock(), légères mais
+ * sans distinction entre lectures et écritures. Tant pis : la réduction de
+ * l'empreinte mémoire prime !
*
* Par contre la documentation indique :
*
@@ -83,23 +74,19 @@ struct _GArchInstruction
* Attempting to lock on two different bits within the same integer is not supported.
* """
*
- * Donc on conserve un compteur distinct pour chaque extrémité.
+ * Donc on doit bien conserver un compteur distinct pour chaque extrémité.
+ * Cela correspond de toute façon à la définition optimisée des tableaux
+ * suivante.
*/
- instr_link_t *from; /* Origines des références */
- instr_link_t *to; /* Instructions visées */
- gint from_count; /* Nombre de ces origines */
- gint to_count; /* Nombre de ces destinations */
+ flat_array_t *from; /* Origines des références */
+ flat_array_t *to; /* Instructions visées */
ArchInstrFlag flags; /* Informations complémentaires*/
};
-/* Bit de verrou pour les champs (from|to)_count */
-#define INSTR_LINK_LOCK_BIT 31
-
-
/* Définition générique d'une instruction d'architecture (classe) */
struct _GArchInstructionClass
{
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 4bb2e2d..14e78dc 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -51,29 +51,6 @@ static void g_arch_instruction_finalize(GArchInstruction *);
-/* ------------------- DEFINITION DES LIAISONS ENTRE INSTRUCTIONS ------------------- */
-
-
-/* Dénombre les liens présents à une extrémité donnée. */
-static size_t g_arch_instruction_get_link_counter(GArchInstruction *, bool);
-
-#define g_arch_instruction_get_source_counter(ins) \
- g_arch_instruction_get_link_counter(ins, true)
-
-#define g_arch_instruction_get_destination_counter(ins) \
- g_arch_instruction_get_link_counter(ins, false)
-
-/* Incrémente le nombre de liens définis à une extrémité donnée. */
-static size_t g_arch_instruction_inc_link_counter(GArchInstruction *, bool);
-
-#define g_arch_instruction_inc_source_counter(ins) \
- g_arch_instruction_inc_link_counter(ins, true)
-
-#define g_arch_instruction_inc_destination_counter(ins) \
- g_arch_instruction_inc_link_counter(ins, false)
-
-
-
/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
@@ -147,8 +124,8 @@ static void g_arch_instruction_init(GArchInstruction *instr)
{
instr->operands = NULL;
- instr->from_count = 0;
- instr->to_count = 0;
+ instr->from = NULL;
+ instr->to = NULL;
}
@@ -657,7 +634,6 @@ void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
* *
* Paramètres : instr = instruction à mettre à jour. *
* src = sélection de l'extrémité à traiter. *
-* write = précise le type d'accès prévu (lecture/écriture). *
* lock = indique le sens du verrouillage à mener. *
* *
* Description : Met à disposition un encadrement des accès aux liens. *
@@ -668,80 +644,16 @@ void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *t
* *
******************************************************************************/
-void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool write, bool lock)
+void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock)
{
- volatile gint *address; /* Choix de l'entier à traiter */
+ flat_array_t **array; /* Choix du tableau ciblé */
- address = (src ? &instr->from_count : &instr->to_count);
+ array = (src ? &instr->from : &instr->to);
if (lock)
- g_bit_lock(address, INSTR_LINK_LOCK_BIT);
+ lock_flat_array(array);
else
- g_bit_unlock(address, INSTR_LINK_LOCK_BIT);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* src = sélection de l'extrémité à traiter. *
-* *
-* Description : Dénombre les liens présents à une extrémité donnée. *
-* *
-* Retour : Quantité positive. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t g_arch_instruction_get_link_counter(GArchInstruction *instr, bool src)
-{
- size_t result; /* Nombre de liens à renvoyer */
- volatile gint *address; /* Choix de l'entier à traiter */
-
- address = (src ? &instr->from_count : &instr->to_count);
-
- assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
-
- result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : instr = instruction dont les informations sont à consulter. *
-* src = sélection de l'extrémité à traiter. *
-* *
-* Description : Incrémente le nombre de liens définis à une extrémité donnée.*
-* *
-* Retour : Nouvelle quantité mise à jour. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t g_arch_instruction_inc_link_counter(GArchInstruction *instr, bool src)
-{
- size_t result; /* Nombre de liens à renvoyer */
- volatile gint *address; /* Choix de l'entier à traiter */
-
- address = (src ? &instr->from_count : &instr->to_count);
-
- assert(!g_bit_trylock(address, INSTR_LINK_LOCK_BIT));
-
- result = g_atomic_int_get(address) & ~(1 << INSTR_LINK_LOCK_BIT);
-
- result++;
-
- assert((result & (1 << INSTR_LINK_LOCK_BIT)) == 0);
-
- g_atomic_int_set(address, (1 << INSTR_LINK_LOCK_BIT) | result);
-
- return result;
+ unlock_flat_array(array);
}
@@ -764,18 +676,23 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
bool result; /* Bilan à retourner */
size_t count; /* Nombre de liens à parcourir */
size_t i; /* Boucle de parcours */
+ instr_link_t *dlink; /* Définition de destination */
result = false;
- g_arch_instruction_rlock_dest(instr);
+ g_arch_instruction_lock_dest(instr);
- count = g_arch_instruction_get_destination_counter(instr);
+ count = g_arch_instruction_count_destinations(instr);
for (i = 0; i < count && !result; i++)
- if (instr->to[i].linked == dest)
- result = true;
+ {
+ dlink = g_arch_instruction_get_destination(instr, i);
- g_arch_instruction_runlock_dest(instr);
+ result = (dlink->linked == dest);
+
+ }
+
+ g_arch_instruction_unlock_dest(instr);
return result;
@@ -798,38 +715,30 @@ bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruct
void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
- size_t count; /* Raccourci pour la lecture */
- instr_link_t *new; /* Nouveau lien à définir */
+ instr_link_t new_src; /* Nouveau lien à définir #1 */
+ instr_link_t new_dst; /* Nouveau lien à définir #2 */
/* Côté destination */
- g_arch_instruction_wlock_src(dest);
-
- count = g_arch_instruction_inc_source_counter(dest);
-
- dest->from = (instr_link_t *)realloc(dest->from, count * sizeof(instr_link_t));
-
- new = &dest->from[count - 1];
-
- new->linked = instr;
- new->type = type;
-
- g_arch_instruction_wunlock_src(dest);
+ new_src.linked = instr;
+ new_src.type = type;
/* Côté point de départ */
- g_arch_instruction_wlock_dest(instr);
+ new_dst.linked = dest;
+ new_dst.type = type;
- count = g_arch_instruction_inc_destination_counter(instr);
+ /* Ajout dans le respect d'une cohérence globale */
- instr->to = (instr_link_t *)realloc(instr->to, count * sizeof(instr_link_t));
+ g_arch_instruction_lock_src(dest);
+ g_arch_instruction_lock_dest(instr);
- new = &instr->to[count - 1];
+ add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t));
- new->linked = dest;
- new->type = type;
+ add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t));
- g_arch_instruction_wunlock_dest(instr);
+ g_arch_instruction_unlock_dest(instr);
+ g_arch_instruction_unlock_src(dest);
}
@@ -845,7 +754,7 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
* *
* Retour : true pour une mise à jour réussie, false sinon. *
* *
-* Remarques : Le verrou doit être posé sur les destination de 'instr'. *
+* Remarques : Le verrou doit être posé sur les destinations de 'instr'. *
* *
******************************************************************************/
@@ -854,52 +763,56 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
bool result; /* Bilan à retourner */
size_t count; /* Raccourci pour la lecture */
size_t i; /* Boucle de parcours */
- size_t from_idx; /* Indice côté destination */
- size_t to_idx; /* Indice côté source */
+ instr_link_t *slink; /* Définition de source */
+ instr_link_t *dlink; /* Définition de destination */
result = false;
- assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
-
- g_arch_instruction_wlock_src(dest);
+ g_arch_instruction_lock_src(dest);
/* Côté destination */
- count = g_arch_instruction_get_source_counter(dest);
+ count = g_arch_instruction_count_sources(dest);
for (i = 0; i < count; i++)
- if (dest->from[i].linked == instr && dest->from[i].type == old)
+ {
+ slink = g_arch_instruction_get_source(dest, i);
+
+ if (slink->linked == instr && slink->type == old)
break;
+ }
+
if (i == count)
goto gaicl_exit;
- else
- from_idx = i;
/* Côté point de départ */
- count = g_arch_instruction_get_destination_counter(instr);
+ count = g_arch_instruction_count_destinations(instr);
for (i = 0; i < count; i++)
- if (instr->to[i].linked == dest && instr->to[i].type == old)
+ {
+ dlink = g_arch_instruction_get_destination(instr, i);
+
+ if (dlink->linked == dest && dlink->type == old)
break;
+ }
+
if (i == count)
goto gaicl_exit;
- else
- to_idx = i;
/* Si les deux extrémités sont raccord... */
- dest->from[from_idx].type = new;
+ slink->type = new;
- instr->to[to_idx].type = new;
+ dlink->type = new;
result = true;
gaicl_exit:
- g_arch_instruction_wunlock_src(dest);
+ g_arch_instruction_unlock_src(dest);
return result;
@@ -910,48 +823,45 @@ bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *d
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* *
-* Description : Indique si l'instruction a une ou plusieurs origines. *
+* Description : Fournit la quantité d'instructions pointant vers une autre. *
* *
-* Retour : Bilan de la consultation. *
+* Retour : Nombre de ces origines. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_sources(GArchInstruction *instr)
+size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
{
- size_t count; /* Nombre de liens présents */
-
- assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
+ size_t result; /* Nombre de liens à renvoyer */
- count = g_arch_instruction_get_source_counter(instr);
+ result = count_flat_array_items(instr->from);
- return (count > 0);
+ return result;
}
/******************************************************************************
* *
-* Paramètres : instr = instruction dont les informations sont à consulter.*
-* sources = liste des liens aux instructions d'origine. [OUT] *
+* Paramètres : instr = instruction dont les informations sont à consulter. *
+* index = indice de l'élément à retrouver. *
* *
-* Description : Fournit les origines d'une instruction donnée. *
+* Description : Fournit les détails d'une origine d'une instruction donnée. *
* *
-* Retour : Nombre de ces origines. *
+* Retour : Lien déterminé vers une instruction d'origine. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **sources)
+instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index)
{
- assert(!g_bit_trylock(&instr->from_count, INSTR_LINK_LOCK_BIT));
+ instr_link_t *result; /* Détails présents à renvoyer */
- if (sources != NULL)
- *sources = instr->from;
+ result = get_flat_array_item(instr->from, index, sizeof(instr_link_t));
- return g_arch_instruction_get_source_counter(instr);
+ return result;
}
@@ -960,23 +870,21 @@ size_t g_arch_instruction_get_sources(GArchInstruction *instr, instr_link_t **so
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
* *
-* Description : Indique si l'instruction a une suite autre que la suivante. *
+* Description : Donne le nombre d'instructions non naturellement suivantes. *
* *
-* Retour : Bilan de la consultation. *
+* Retour : Nombre de ces destinations. *
* *
* Remarques : - *
* *
******************************************************************************/
-bool g_arch_instruction_has_destinations(GArchInstruction *instr)
+size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
{
- size_t count; /* Nombre de liens présents */
-
- assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+ size_t result; /* Nombre de liens à renvoyer */
- count = g_arch_instruction_get_destination_counter(instr);
+ result = count_flat_array_items(instr->to);
- return (count > 0);
+ return result;
}
@@ -984,24 +892,23 @@ bool g_arch_instruction_has_destinations(GArchInstruction *instr)
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
-* dests = liste de liens aux instructions de destination. [OUT]*
+* index = indice de l'élément à retrouver. *
* *
-* Description : Fournit les destinations d'une instruction donnée. *
+* Description : Fournit les détails d'une destination d'une instruction. *
* *
-* Retour : Nombre de ces destinations. *
+* Retour : Lien déterminé vers une instruction de destination. *
* *
* Remarques : - *
* *
******************************************************************************/
-size_t g_arch_instruction_get_destinations(GArchInstruction *instr, instr_link_t **dests)
+instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index)
{
- assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+ instr_link_t *result; /* Détails présents à renvoyer */
- if (dests != NULL)
- *dests = instr->to;
+ result = get_flat_array_item(instr->to, index, sizeof(instr_link_t));
- return g_arch_instruction_get_destination_counter(instr);
+ return result;
}
@@ -1024,53 +931,28 @@ GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *ins
GArchInstruction *result; /* Résultat à remonter */
size_t count; /* Nombre de liens à parcourir */
size_t i; /* Boucle de parcours */
+ instr_link_t *dest; /* Destination à étudier */
result = NULL;
- assert(!g_bit_trylock(&instr->to_count, INSTR_LINK_LOCK_BIT));
+ g_arch_instruction_lock_dest(instr);
- count = g_arch_instruction_get_destination_counter(instr);
+ count = g_arch_instruction_count_destinations(instr);
for (i = 0; i < count && result == NULL; i++)
- if (instr->to[i].type == type)
- result = instr->to[i].linked;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : iter = membre du groupe donné en référence. *
-* list = liste des instructions à analyser. *
-* count = taille de cette liste. *
-* *
-* Description : Indique la position dans les instructions identiques. *
-* *
-* Retour : Indice dans les instructions identiques du groupe. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-size_t g_arch_instruction_compute_group_index(GArchInstruction **iter, GArchInstruction **list, size_t count)
-{
- size_t result; /* Valeur à retourner */
- size_t i; /* Boucle de parcours */
-
- result = 0;
-
- for (i = 0; i < count; i++)
{
- if ((list + i) == iter)
- break;
+ dest = g_arch_instruction_get_destination(instr, i);
- if (list[i] == *iter)
- result++;
+ if (dest->type == type)
+ {
+ result = dest->linked;
+ g_object_ref(G_OBJECT(result));
+ }
}
+ g_arch_instruction_unlock_dest(instr);
+
return result;
}
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index d38bb62..bb2dc94 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -215,7 +215,7 @@ typedef struct _instr_link_t
/* Met à disposition un encadrement des accès aux liens. */
-void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool, bool);
+void g_arch_instruction_lock_unlock_links(GArchInstruction *, bool, bool);
/* Détermine si un lien est déjà établi entre deux instructions. */
bool g_arch_instruction_has_link_to(GArchInstruction *, const GArchInstruction *);
@@ -226,36 +226,27 @@ void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, Instru
/* Change la nature d'un lien entre deux instructions. */
bool g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
-#define g_arch_instruction_wlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true, true)
-#define g_arch_instruction_wunlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true, false)
+#define g_arch_instruction_lock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, true)
+#define g_arch_instruction_unlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false)
-#define g_arch_instruction_rlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false, true)
-#define g_arch_instruction_runlock_src(ins) g_arch_instruction_lock_unlock_links(ins, true, false, false)
+/* Fournit la quantité d'instructions pointant vers une autre. */
+size_t g_arch_instruction_count_sources(const GArchInstruction *);
-/* Indique si l'instruction a une ou plusieurs origines. */
-bool g_arch_instruction_has_sources(GArchInstruction *);
+/* Fournit les détails d'une origine d'une instruction donnée. */
+instr_link_t *g_arch_instruction_get_source(GArchInstruction *, size_t);
-/* Fournit les origines d'une instruction donnée. */
-size_t g_arch_instruction_get_sources(GArchInstruction *, instr_link_t **);
+#define g_arch_instruction_lock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true)
+#define g_arch_instruction_unlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false)
-#define g_arch_instruction_wlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true, true)
-#define g_arch_instruction_wunlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, true, false)
+/* Donne le nombre d'instructions non naturellement suivantes. */
+size_t g_arch_instruction_count_destinations(const GArchInstruction *);
-#define g_arch_instruction_rlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false, true)
-#define g_arch_instruction_runlock_dest(ins) g_arch_instruction_lock_unlock_links(ins, false, false, false)
-
-/* Indique si l'instruction a une suite autre que la suivante. */
-bool g_arch_instruction_has_destinations(GArchInstruction *);
-
-/* Fournit les destinations d'une instruction donnée. */
-size_t g_arch_instruction_get_destinations(GArchInstruction *, instr_link_t **);
+/* Fournit les détails d'une destination d'une instruction. */
+instr_link_t *g_arch_instruction_get_destination(GArchInstruction *, size_t);
/* Fournit la destination d'une instruction et d'un type donné. */
GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *, InstructionLinkType);
-/* Indique la position dans les instructions identiques. */
-size_t g_arch_instruction_compute_group_index(GArchInstruction **, GArchInstruction **, size_t);
-
/* --------------------- CONVERSIONS DU FORMAT DES INSTRUCTIONS --------------------- */