diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/instruction-int.h | 31 | ||||
-rw-r--r-- | src/arch/instruction.c | 296 | ||||
-rw-r--r-- | src/arch/instruction.h | 35 |
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 --------------------- */ |