diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-01-20 13:10:06 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-01-20 13:10:06 (GMT) |
commit | 37fd2f1329c56078bc8a8b2fc955aa001c109c01 (patch) | |
tree | 71bcce9a3eaf6b7569d1f1d3e057752ae517ebde /src/decomp/context.c | |
parent | a9bbd894bd25f7c2bb72fb7d4064b19377d90c6d (diff) |
Took care of shared allocations between blocks when converting registers.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@326 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/decomp/context.c')
-rw-r--r-- | src/decomp/context.c | 203 |
1 files changed, 201 insertions, 2 deletions
diff --git a/src/decomp/context.c b/src/decomp/context.c index 025c0d2..ef5c25e 100644 --- a/src/decomp/context.c +++ b/src/decomp/context.c @@ -89,6 +89,11 @@ static void g_dec_context_class_init(GDecContextClass *class) static void g_dec_context_init(GDecContext *ctx) { + ctx->awaited = g_raccess_list_new(); + + ctx->shared = g_hash_table_new_full((GHashFunc)g_arch_register_hash, + (GEqualFunc)g_arch_register_equal, + g_object_unref, g_object_unref); } @@ -113,6 +118,9 @@ static void g_dec_context_dispose(GDecContext *ctx) if (ctx->routine != NULL) g_object_unref(G_OBJECT(ctx->routine)); + g_object_unref(G_OBJECT(ctx->awaited)); + g_hash_table_unref(ctx->shared); + G_OBJECT_CLASS(g_dec_context_parent_class)->dispose(G_OBJECT(ctx)); } @@ -227,6 +235,135 @@ GExeFormat *g_dec_context_get_format(const GDecContext *ctx) { return ctx->format; +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* awaited = liste des registres impliqués dans plusieurs blocs.* +* * +* Description : Définit la liste des registrés utilisés dans plusieurs blocs.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_set_awaited(GDecContext *ctx, GRAccessList *awaited) +{ + g_object_unref(G_OBJECT(ctx->awaited)); + + g_object_ref(G_OBJECT(awaited)); + ctx->awaited = awaited; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter. * +* * +* Description : Fournit la liste des registrés utilisés dans plusieurs blocs.* +* * +* Retour : Liste des registres impliqués dans plusieurs blocs. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const GRAccessList *g_dec_context_get_awaited(const GDecContext *ctx) +{ + return ctx->awaited; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à mettre à jour. * +* shared = liste des allocations passées de registres attendus.* +* * +* Description : Définit la liste des registrés déjà alloués et attendus. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_set_shared_allocs(GDecContext *ctx, GHashTable *shared) +{ + g_hash_table_unref(ctx->shared); + + g_hash_table_ref(shared); + ctx->shared = shared; + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter. * +* * +* Description : Fournit la liste des registrés déjà alloués et attendus. * +* * +* Retour : Liste des allocations passées de registres attendus. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GHashTable *g_dec_context_get_shared_allocs(const GDecContext *ctx) +{ + return ctx->shared; + +} + + +/****************************************************************************** +* * +* Paramètres : parent = instance à éventuellement compléter. * +* child = instance à venir consulter. * +* * +* Description : Propage les registres alloués et attendus par la suite. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_spread_allocated_shared_regs(GDecContext *parent, GDecContext *child) +{ + GHashTableIter iter; /* Boucle de parcours */ + GArchRegister *reg; /* Registre converti */ + GDecInstruction *dinstr; /* Expression décompilée */ + + g_hash_table_iter_init(&iter, child->shared); + + while (g_hash_table_iter_next(&iter, (gpointer *)®, (gpointer *)&dinstr)) + { + /** + * La liste des allocations attendues du bloc virtuel parent, et donc de + * son contexte associé, englobe les attentes des blocs contenus. + * Même si ce bloc parent n'est pas responsable directement de ces allocations, + * on fait remonter ces dernières pour la propagation dans les blocs suivants + * le bloc parent. + */ + if (g_raccess_list_find(parent->awaited, reg) != NULL) + { + g_object_ref(G_OBJECT(reg)); + g_object_ref(G_OBJECT(dinstr)); + + g_hash_table_insert(parent->shared, reg, dinstr); + + } + + parent->spread(parent, reg, dinstr); + + } } @@ -276,6 +413,7 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr) * Paramètres : ctx = instance à consulter, voire mettre à jour. * * operand = opérande représentant un registre quelconque. * * assign = précise le sort prochain du registre. * +* addr = adresse de l'instruction décompilée. * * * * Description : Convertit un registre machine en un pseudo-registre. * * * @@ -285,8 +423,69 @@ void g_dec_context_set_decomp_instrs(GDecContext *ctx, GDecInstruction *instr) * * ******************************************************************************/ -GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign) +GDecInstruction *g_dec_context_convert_register(GDecContext *ctx, gpointer operand, bool assign, vmpa_t addr) +{ + return ctx->convert_reg(ctx, operand, assign, addr); + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter, voire mettre à jour. * +* reg = registre à l'origine de l'allocation. * +* dinstr = élément décompilé résultant. * +* addr = adresse de l'instruction décompilée. * +* * +* Description : Sauvegarde une conversion de registre si elle est attendue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_dec_context_notify_reg_alloc(GDecContext *ctx, GArchRegister *reg, GDecInstruction *dinstr, vmpa_t addr) +{ + reg_access *access; /* Attente rélle si existante */ + + access = g_raccess_list_find(ctx->awaited, reg); + + if (access != NULL && access->last_write == addr) + { + g_object_ref(G_OBJECT(reg)); + g_object_ref(G_OBJECT(dinstr)); + + g_hash_table_insert(ctx->shared, reg, dinstr); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : ctx = instance à consulter, voire mettre à jour. * +* reg = registre à convertir prochainement. * +* addr = adresse de l'instruction décompilée. * +* * +* Description : Fournit une conversiond de registre déjà faite et attendue. * +* * +* Retour : Elément déjà décompilé dans une autre branche. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GDecInstruction *g_dec_context_get_awaited_alloc(GDecContext *ctx, GArchRegister *reg, vmpa_t addr) { - return ctx->convert_reg(ctx, operand, assign); + reg_access *access; /* Attente rélle si existante */ + + access = g_raccess_list_find(ctx->awaited, reg); + if (access == NULL) return NULL; + + if (access->last_write != addr) return NULL; + + return G_DEC_INSTRUCTION(g_hash_table_lookup(ctx->shared, reg)); } |