summaryrefslogtreecommitdiff
path: root/src/decomp/context.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-01-20 13:10:06 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-01-20 13:10:06 (GMT)
commit37fd2f1329c56078bc8a8b2fc955aa001c109c01 (patch)
tree71bcce9a3eaf6b7569d1f1d3e057752ae517ebde /src/decomp/context.c
parenta9bbd894bd25f7c2bb72fb7d4064b19377d90c6d (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.c203
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 *)&reg, (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));
}