summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-04-05 23:12:13 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-04-05 23:12:13 (GMT)
commit40d624af29e752bb4255099ab3f1de64e3c96dd3 (patch)
tree3491d98e4358f9f8e84825478a3701d7fbb317ce
parentfd679be33396b0ba85ba6617b33a66d221026d91 (diff)
Fixed various bugs in the graph layout.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@504 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
-rw-r--r--ChangeLog21
-rw-r--r--src/analysis/disass/loop.c2
-rw-r--r--src/arch/instruction.c62
-rw-r--r--src/arch/instruction.h3
-rw-r--r--src/gtkext/graph/edge.c2
-rw-r--r--src/gtkext/graph/node.c9
-rw-r--r--src/gtkext/graph/nodes/flow.c46
-rw-r--r--src/gtkext/graph/nodes/virtual.c106
8 files changed, 142 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index ab7eb20..2660ff1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+15-04-06 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/analysis/disass/loop.c:
+ Update code when creating loops.
+
+ * src/arch/instruction.c:
+ * src/arch/instruction.h:
+ Provide a way to properly change an existing link between instructions.
+
+ * src/gtkext/graph/edge.c:
+ Change the direction for looping edges to left.
+
+ * src/gtkext/graph/node.c:
+ Upgrade code. Set a pending position only one time.
+
+ * src/gtkext/graph/nodes/flow.c:
+ Align vertical edges when there is a loop edge in the final block entries.
+
+ * src/gtkext/graph/nodes/virtual.c:
+ Fix the position of loop edges.
+
15-04-05 Cyrille Bagard <nocbos@gmail.com>
* src/gtkext/graph/layout.c:
diff --git a/src/analysis/disass/loop.c b/src/analysis/disass/loop.c
index 0cb346b..44fa6d5 100644
--- a/src/analysis/disass/loop.c
+++ b/src/analysis/disass/loop.c
@@ -269,7 +269,7 @@ static void track_loops_in_code(const GArchProcessor *proc, const mrange_t *rang
addr = get_mrange_addr(irange);
if (!is_new_exec_flow(flow, addr))
- types[i] = ILT_LOOP;
+ /* status = */g_arch_instruction_change_link(iter, dests[i], types[i], ILT_LOOP);
else
{
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index 08256d1..475c038 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -624,6 +624,68 @@ void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *des
/******************************************************************************
* *
* Paramètres : instr = instruction dont les informations sont à consulter. *
+* dest = ligne visée par la liaison (côté destination). *
+* old = ancien type de lien construit. *
+* new = nouveau type de lien à construire. *
+* *
+* Description : Change la nature d'un lien entre deux instructions. *
+* *
+* Retour : true pour une mise à jour réussie, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
+{
+ 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 */
+
+ /* Côté destination */
+
+ count = dest->from_count;
+
+ for (i = 0; i < count; i++)
+ if (dest->from[i] == instr && dest->from_types[i] == old)
+ break;
+
+ if (i == count)
+ return false;
+ else
+ from_idx = i;
+
+ /* Côté point de départ */
+
+ count = instr->to_count;
+
+ for (i = 0; i < count; i++)
+ if (instr->to[i] == dest && instr->to_types[i] == old)
+ break;
+
+ if (i == count)
+ return false;
+ else
+ to_idx = i;
+
+ /* Si les deux extrémités sont raccord... */
+
+ dest->from_types[from_idx] = new;
+
+ instr->to_types[to_idx] = new;
+
+ return true;
+
+
+ /* TODO : si les informations complémentaires restent en place, compléter ! */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction dont les informations sont à consulter. *
* *
* Description : Indique si l'instruction a une ou plusieurs origines. *
* *
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 0198bb5..9123b6f 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -188,6 +188,9 @@ bool g_arch_instruction_is_return(const GArchInstruction *instr);
/* Etablit un lien entre deux instructions. */
void g_arch_instruction_link_with(GArchInstruction *, GArchInstruction *, InstructionLinkType, ...);
+/* Change la nature d'un lien entre deux instructions. */
+void g_arch_instruction_change_link(GArchInstruction *, GArchInstruction *, InstructionLinkType, InstructionLinkType);
+
/* Indique si l'instruction a une ou plusieurs origines. */
bool g_arch_instruction_has_sources(const GArchInstruction *);
diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c
index cd312cb..acd164c 100644
--- a/src/gtkext/graph/edge.c
+++ b/src/gtkext/graph/edge.c
@@ -238,7 +238,7 @@ void g_graph_edge_reserve_vertical_space(GGraphEdge *edge, GGraphNode *nodes, GG
g_object_ref(G_OBJECT(container));
edge->container = G_VIRTUAL_NODE(container);
- edge->is_left = false; /* TODO */
+ edge->is_left = true; /* TODO */
r1 = g_graph_node_get_rank(G_GRAPH_NODE(edge->src_node));
r2 = g_graph_node_get_rank(G_GRAPH_NODE(edge->dest_node));
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c
index 3801d1a..ec09941 100644
--- a/src/gtkext/graph/node.c
+++ b/src/gtkext/graph/node.c
@@ -24,6 +24,7 @@
#include "node.h"
+#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
@@ -258,6 +259,8 @@ void g_graph_node_reset_position(GGraphNode *node)
node->alloc.x = UNINITIALIZED_NODE_POS;
node->alloc.y = UNINITIALIZED_NODE_POS;
+ node->pending_flag = PPF_NONE;
+
if (node->reset_pos != NULL)
node->reset_pos(node);
@@ -307,18 +310,21 @@ void g_graph_node_apply_position(GGraphNode *node)
switch (node->pending_flag)
{
case PPF_DIRECT_X:
+ assert(g_graph_node_has_x_position(node->pending_rel));
g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
x_pos += node->pending_pos.direct_x;
g_graph_node_set_x_position(node, x_pos);
break;
case PPF_LEFT_MARGIN:
+ assert(g_graph_node_has_x_position(node->pending_rel));
g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
x_pos += EDGE_SLOT_HORIZ_MARGIN + node->pending_pos.left_margin;
g_graph_node_set_x_position(node, x_pos);
break;
case PPF_RIGHT_MARGIN:
+ assert(g_graph_node_has_x_position(node->pending_rel));
g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
x_pos += node->pending_pos.right_margin;
x_pos -= (EDGE_SLOT_HORIZ_MARGIN + node->alloc.width);
@@ -386,6 +392,9 @@ void g_graph_node_set_x_position(GGraphNode *node, gint x)
void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos, GGraphNode *rel)
{
+ if (node->pending_flag != PPF_NONE)
+ return;
+
node->pending_pos = pos;
node->pending_flag = flag;
node->pending_rel = rel;
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index 5173810..863d86c 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -299,6 +299,7 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
{
GGraphNode *base; /* Autre vision de l'instance */
GArchInstruction *last; /* Dernière instr. du noeud */
+ size_t loop_index; /* Indice de sortie en boucle */
GFlowNode *target; /* Bloc visé par le lien */
node_slot_t *dest_slot; /* Accrochage d'arrivée */
pending_position pos; /* Position à transmettre */
@@ -312,25 +313,52 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
g_flow_block_get_boundary(node->block, NULL, &last);
- switch (node->exits_count)
+ for (loop_index = 0; loop_index < node->exits_count; loop_index++)
+ if (node->exits[loop_index].type == ILT_LOOP)
+ break;
+
+ switch (node->exits_count - (loop_index == node->exits_count ? 0 : 1))
{
case 0:
break;
case 1:
- if (node->exits[0].type == ILT_LOOP)
- break;
+ if (loop_index == node->exits_count)
+ {
+ target = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
+
+ dest_slot = g_flow_node_get_slot(target, true,
+ last, node->exits[0].group_index);
- target = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
+ }
+ else
+ {
+ target = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[1].instr));
- dest_slot = g_flow_node_get_slot(target, true,
- last, node->exits[0].group_index);
+ dest_slot = g_flow_node_get_slot(target, true,
+ last, node->exits[1].group_index);
+
+ }
pos.direct_x = g_flow_node_get_slot_offset(target, true, dest_slot);
pos.direct_x = (G_GRAPH_NODE(target)->alloc.width / 2) - pos.direct_x;
- if (target->entries_count == 1)
+ pos.direct_x -= (G_GRAPH_NODE(target)->alloc.width - G_GRAPH_NODE(node)->alloc.width) / 2;
+
+ size_t count_and_skip_loop(GFlowNode *n)
+ {
+ size_t counter;
+
+ for (counter = 0; counter < n->entries_count; counter++)
+ if (n->entries[counter].type == ILT_LOOP)
+ break;
+
+ return counter < n->entries_count ? n->entries_count - 1 : n->entries_count;
+
+ }
+
+ if (count_and_skip_loop(target) == 1)
g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos, base);
break;
@@ -678,7 +706,7 @@ static void g_flow_node_setup_entry_slots(GFlowNode *node)
node->entries[used].type = types[i];
node->entries[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
- instrs, icount);
+ instrs, icount);
node->entries[used].slot_index = i;
used++;
@@ -769,7 +797,7 @@ static void g_flow_node_setup_exit_slots(GFlowNode *node)
node->exits[used].type = types[i];
node->exits[used].group_index = g_arch_instruction_compute_group_index(&instrs[i],
- instrs, icount);
+ instrs, icount);
node->exits[used].slot_index = i;
used++;
diff --git a/src/gtkext/graph/nodes/virtual.c b/src/gtkext/graph/nodes/virtual.c
index e04ff5d..cb46aee 100644
--- a/src/gtkext/graph/nodes/virtual.c
+++ b/src/gtkext/graph/nodes/virtual.c
@@ -24,6 +24,7 @@
#include "virtual.h"
+#include <assert.h>
#include <malloc.h>
#include <sys/param.h>
@@ -365,7 +366,6 @@ static void g_virtual_node_finalize(GVirtualNode *node)
/******************************************************************************
* *
* Paramètres : block = bloc virtuel représenté graphiquement. *
-* view = morceau d'affichage à représenter. *
* *
* Description : Encapsule graphiquement un bloc virtuel. *
* *
@@ -489,12 +489,14 @@ static void g_virtual_node_apply_position(GVirtualNode *node)
}
/* Espace pour les liens remontants */
+
if (node->left_count > 0)
offset = EDGE_SLOT_HORIZ_MARGIN + EDGE_HORIZONTAL_MIN_SEP * (node->left_count - 1);
else
offset = 0;
/* Ajout du décallage le plus grand */
+
offset += -min;
/* Traitement des sous-noeuds */
@@ -543,14 +545,14 @@ static void g_virtual_node_apply_x_line(GVirtualNode *node)
{
level = &node->levels[i];
- /* Si l'ensemble de l'étage doit être aligné */
+ /* Si l'ensemble de l'étage doit être centré */
if (level->children[0]->pending_flag == PPF_NONE)
{
width_sum = 0;
for (j = 0; j < level->count; j++)
{
- /* BUG_ON(level->children[j]->pending_flag != PPF_NONE); */
+ assert(level->children[j]->pending_flag == PPF_NONE);
g_graph_node_apply_position(level->children[j]);
width_sum += level->children[j]->alloc.width;
@@ -698,98 +700,6 @@ static void g_virtual_node_set_position(GVirtualNode *node, gint x)
/******************************************************************************
* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Indique l'espace requis pour un noeud d'encapsulation. *
-* *
-* Retour : Espace constitué, entièrement ou non. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkAllocation g_virtual_node_get_allocation(const GVirtualNode *node)
-{
- GtkAllocation result; /* Valeurs à retourner */
- gint margins; /* Bordures gauche et droite */
- unsigned int last_rank; /* Détection de saut de rangs */
- size_t vert_count; /* Quantité à la verticale */
- gint rank_width; /* Largeur d'un rang donné */
- gint rank_height; /* Hauteur d'un rang donné */
- size_t i; /* Boucle de parcours */
- GtkAllocation alloc; /* Allocation d'un sous-noeud */
-
- result.x = node->x;
- result.y = node->y;
-
- result.width = 0;
- margins = 0;
- if (node->left_count > 0)
- {
- margins += EDGE_SLOT_HORIZ_MARGIN;
- margins += (node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP;
- }
- if (node->right_count > 0)
- {
- margins += EDGE_SLOT_HORIZ_MARGIN;
- margins += (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP;
- }
- result.height = 0;
-
- last_rank = -1;
-
- vert_count = 0;
-
- rank_width = 0;
- rank_height = 0;
-
- for (i = 0; i < node->count; i++)
- {
- alloc = g_graph_node_get_allocation(node->children[i]);
-
- /* Prise en compte de l'étage précédent */
- if (last_rank != g_graph_node_get_rank(node->children[i]))
- {
- last_rank = g_graph_node_get_rank(node->children[i]);
-
- result.width = MAX(result.width, rank_width);
- result.height += rank_height;
-
- rank_width = 0;
- rank_height = 0;
-
- vert_count++;
-
- }
-
- /* Mise à jour de l'étage courant */
-
- if (node->x == UNINITIALIZED_NODE_POS)
- {
- rank_width += alloc.width;
- if (rank_width > 0) rank_width += NODE_LEFT_MARGIN;
- }
- else
- rank_width = MAX(alloc.x + alloc.width - node->x, rank_width);
-
- rank_height = MAX(rank_height, alloc.height);
-
- }
-
- result.width = MAX(result.width, rank_width);
-
- result.width += margins;
-
- if (vert_count > 1)
- result.height += (vert_count - 1) * NODE_TOP_MARGIN;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
* Paramètres : node = noeud graphique démarrant la visite. *
* callback = ensemble de blocs à parcourir. *
* data = donnée utilisateur à associer au parcours. *
@@ -1026,14 +936,14 @@ gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *node, vspan_slot_t
gint result; /* Position à retourner */
GtkAllocation alloc; /* Taille totale requise */
- alloc = g_virtual_node_get_allocation(node);
+ alloc = G_GRAPH_NODE(node)->alloc;
if (left)
{
/*BUG_ON(slot >= node->left_count) */
- result = (node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/;
- result -= (slot * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/);
+ result = -(node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/;
+ result += (slot * EDGE_HORIZONTAL_MIN_SEP/* + EDGE_SLOT_HORIZ_MARGIN*/);
result += alloc.x;