* Copyright: (c) 2002-2003 Universität Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
-
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+
#include <stdbool.h>
#include "ircgcons.h"
#include "array.h"
#include "irprog.h"
-#include "ircons.h"
+#include "irnode_t.h"
+#include "irprog_t.h"
+#include "ircons_t.h"
#include "irgmod.h"
#include "irgwalk.h"
-#include "irflag.h"
+#include "irflag_t.h"
+#include "irtools.h"
+/* Return the current state of the interprocedural view. */
+ip_view_state get_irp_ip_view_state(void) {
+ return irp->ip_view;
+}
+
+/* Set the current state of the interprocedural view. */
+static void set_irp_ip_view(ip_view_state state) {
+ irp->ip_view = state;
+}
-/* Datenstruktur für jede Methode */
+/* Set the state of the interprocedural view to invalid. */
+void set_irp_ip_view_invalid(void) {
+ set_irp_ip_view(ip_view_invalid);
+}
+
+
+/* Data for each method */
typedef struct {
- int count;
- bool open; /* offene Methode (mit unbekanntem Aufrufer) */
- ir_node * reg, * mem, ** res; /* EndReg, Mem und Rückgabewerte */
- ir_node * except, * except_mem; /* EndExcept und Mem für Ausnahmeabbruch */
+ int count; /* Number of calleers. */
+ bool open; /* Open method: called by an unknown caller */
+ ir_node * reg, * mem, ** res; /* EndReg, Mem and Method return values */
+ ir_node * except, * except_mem; /* EndExcept and Mem for exception return */
} irg_data_t;
-
static irg_data_t * irg_data_create(void) {
- irg_data_t * data = xmalloc(sizeof(irg_data_t));
- memset(data, 0, sizeof(irg_data_t)); /* init */
+ irg_data_t *data = xmalloc(sizeof(*data));
+ memset(data, 0, sizeof(*data)); /* init */
return data;
}
-
-/* Die Anzahl der Aufrufer jeder Methode zählen (irg_data_t->count), und die
- * offenen Methoden (mit unbekannten Vorgänger) markieren. */
+/** Count the number of callers of each method and mark open methods.
+ *
+ * Fills the irg_data data structure.
+ * Open methods are methods with an unknown caller, I.e., methods that
+ * - are external visible
+ * - are dereferenced somewhere within the program (i.e., the address of the
+ * method is stored somewhere). */
static void caller_init(int arr_length, entity ** free_methods) {
int i, j;
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- set_entity_link(get_irg_ent(get_irp_irg(i)), irg_data_create());
+ set_entity_link(get_irg_entity(get_irp_irg(i)), irg_data_create());
}
for (i = arr_length - 1; i >= 0; --i) {
irg_data_t * data = get_entity_link(free_methods[i]);
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph * irg = get_irp_irg(i);
ir_node * call;
- /* Die Call-Knoten sind (mit den Proj-Knoten) am End-Knoten verlinkt! */
+ /* We collected all call nodes in a link list at the end node. */
for (call = get_irn_link(get_irg_end(irg)); call; call = get_irn_link(call)) {
if (get_irn_op(call) != op_Call) continue;
for (j = get_Call_n_callees(call) - 1; j >= 0; --j) {
- entity * ent = get_Call_callee(call, j);
- if (ent) {
- irg_data_t * data = get_entity_link(ent);
- assert(get_entity_irg(ent) && data);
- ++data->count;
- }
+ entity * ent = get_Call_callee(call, j);
+ if (get_entity_irg(ent)) {
+ irg_data_t * data = get_entity_link(ent);
+# ifndef CATE_jni
+ assert(get_entity_irg(ent) && data);
+ ++data->count;
+# endif /* ndef CATE_jni */
+ } else {
+ set_entity_link(ent, NULL);
+ }
}
}
}
}
-
-static INLINE void clear_link(ir_node * node, void * env) {
- set_irn_link(node, NULL);
-}
-
/*
static INLINE ir_node * tail(ir_node * node) {
ir_node * link;
*call_tail = node;
}
} else if (get_irn_op(node) == op_Phi) {
- ir_node * block = get_nodes_Block(node);
+ ir_node * block = get_nodes_block(node);
set_irn_link(node, get_irn_link(block));
set_irn_link(block, node);
}
link(start, get_irg_frame(irg));
link(start, get_irg_globals(irg));
/* walk */
- irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_phicallproj_walker, &end);
+ irg_walk_graph(irg, firm_clear_link, (irg_walk_func *) collect_phicallproj_walker, &end);
}
}
ir_node * filter;
assert(get_irn_op(proj) == op_Proj);
filter = new_Filter(get_Proj_pred(proj), get_irn_mode(proj), get_Proj_proj(proj));
- assert(get_Proj_proj(proj) == get_Filter_proj(filter)); /* XXX:SID */
/* Die Proj- (Id-) Operation sollte im gleichen Grundblock stehen, wie die
* Filter-Operation. */
- set_nodes_Block(proj, get_nodes_Block(filter));
+ set_nodes_block(proj, get_nodes_block(filter));
exchange(proj, filter);
return filter;
}
/* Echt neue Block-Operation erzeugen. CSE abschalten! */
static ir_node * create_Block(int n, ir_node ** in) {
/* Turn off optimizations so that blocks are not merged again. */
- int rem_opt = get_optimize();
+ int rem_opt = get_opt_optimize();
ir_node * block;
set_optimize(0);
block = new_Block(n, in);
static void prepare_irg_end_except(ir_graph * irg, irg_data_t * data);
+/* If we use new_Unknown we get the Unknown of a graph. This can
+ * cause cycles we don't want to see, as Unknwon is in the Start Block
+ * of the procedure. Use unknown of outermost irg where the start
+ * block has no predecessors. */
+static INLINE ir_node *get_cg_Unknown(ir_mode *m) {
+ assert((get_Block_n_cfgpreds(get_irg_start_block(get_irp_main_irg())) == 1) &&
+ (get_nodes_block(get_Block_cfgpred(get_irg_start_block(get_irp_main_irg()), 0)) ==
+ get_irg_start_block(get_irp_main_irg())));
+ return new_r_Unknown(get_irp_main_irg(), m);
+}
+
+
/* IRG vorbereiten. Proj-Operationen der Start-Operation in Filter-Operationen
* umwandeln. Die künstlichen Steuerzusammenflüsse EndReg und EndExcept
* einfügen. An der Start-Operation hängt nach dem Aufruf eine Liste der
* den Start-Block verschieben. */
for (proj = get_irn_link(get_irg_start(irg)); proj; proj = get_irn_link(proj)) {
if (get_Proj_pred(proj) != get_irg_start(irg)
- || (get_Proj_proj(proj) != pns_initial_exec && get_Proj_proj(proj) != pns_args)) {
+ || (get_Proj_proj(proj) != pn_Start_X_initial_exec && get_Proj_proj(proj) != pn_Start_T_args)) {
ir_node * filter = exchange_proj(proj);
set_Filter_cg_pred_arr(filter, n_callers, in);
} else {
- set_nodes_Block(proj, start_block);
+ set_nodes_block(proj, start_block);
}
}
ir_node * filter = get_Id_pred(proj);
assert(get_irn_op(filter) == op_Filter);
if (filter != link && get_irn_link(filter) == NULL) {
- set_irn_link(link, filter);
- link = filter;
+ set_irn_link(link, filter);
+ link = filter;
}
}
}
/* Globle Einträge für ersetzte Operationen korrigieren. */
- set_irg_frame(irg, skip_nop(get_irg_frame(irg)));
- set_irg_globals(irg, skip_nop(get_irg_globals(irg)));
+ set_irg_frame (irg, skip_Id(get_irg_frame(irg)));
+ set_irg_globals (irg, skip_Id(get_irg_globals(irg)));
+ set_irg_initial_mem(irg, skip_Id(get_irg_initial_mem(irg)));
/* Unbekannten Aufrufer sofort eintragen. */
if (data->open) {
- set_Block_cg_cfgpred(start_block, 0, new_Unknown());
+ set_Block_cg_cfgpred(start_block, 0, get_cg_Unknown(mode_X));
for (proj = get_irn_link(get_irg_start(irg)); proj; proj = get_irn_link(proj)) {
if (get_irn_op(proj) == op_Filter) {
- set_Filter_cg_pred(proj, 0, new_Unknown());
+ set_Filter_cg_pred(proj, 0, get_cg_Unknown(get_irn_mode(proj)));
}
}
data->count = 1;
/* Künstlicher Steuerzusammenfluss EndReg einfügen. */
static void prepare_irg_end(ir_graph * irg, irg_data_t * data) {
- ir_node * end_block = get_irg_end_block(irg);
- ir_node * end = get_irg_end(irg);
- ir_node ** ret_arr = NULL;
+ ir_node * end_block = get_irg_end_block(irg);
+ ir_node * end = get_irg_end(irg);
+ ir_node **ret_arr = NULL;
+ ir_node **cfgpred_arr = get_Block_cfgpred_arr(end_block);
int i, j;
int n_ret = 0;
- ir_node ** cfgpred_arr = get_Block_cfgpred_arr(end_block);
+
for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
- if (get_irn_op(cfgpred_arr[i]) == op_Return) {
+ if (is_Return(cfgpred_arr[i])) {
if (ret_arr) {
- ARR_APP1(ir_node *, ret_arr, cfgpred_arr[i]);
+ ARR_APP1(ir_node *, ret_arr, cfgpred_arr[i]);
} else {
- ret_arr = NEW_ARR_F(ir_node *, 1);
- ret_arr[0] = cfgpred_arr[i];
+ ret_arr = NEW_ARR_F(ir_node *, 1);
+ ret_arr[0] = cfgpred_arr[i];
}
++n_ret;
}
}
+
if (n_ret > 0) {
- int n_res = get_method_n_ress(get_entity_type(get_irg_ent(irg)));
+ int n_res = get_method_n_ress(get_entity_type(get_irg_entity(irg)));
ir_node ** in = NEW_ARR_F(ir_node *, n_ret);
+
/* block */
for (i = n_ret - 1; i >= 0; --i) {
- set_irg_current_block(irg, get_nodes_Block(ret_arr[i]));
+ set_irg_current_block(irg, get_nodes_block(ret_arr[i]));
in[i] = new_Jmp();
}
create_Block(n_ret, in);
+
/* end */
data->reg = new_EndReg();
+
/* mem */
for (i = n_ret - 1; i >= 0; --i) {
in[i] = get_Return_mem(ret_arr[i]);
}
data->mem = new_Phi(n_ret, in, mode_M);
- /* This Phi is a merge, therefor needs not be kept alive.
+ /* This Phi is a merge, therefore needs not be kept alive.
It might be optimized away, though. */
if (get_End_keepalive(end, get_End_n_keepalives(end)-1 ) == data->mem)
set_End_keepalive(end, get_End_n_keepalives(end)-1, new_Bad());
+
/* res */
data->res = NEW_ARR_F(ir_node *, n_res);
for (j = n_res - 1; j >= 0; --j) {
else /* All preds are Bad */
data->res[j] = new_Bad();
}
+
DEL_ARR_F(in);
}
+
if (ret_arr) DEL_ARR_F(ret_arr);
}
int n_except = 0;
ir_node ** cfgpred_arr = get_Block_cfgpred_arr(end_block);
for (i = get_Block_n_cfgpreds(end_block) - 1; i >= 0; --i) {
- if (get_irn_op(cfgpred_arr[i]) != op_Return) {
+ if (! is_Return(cfgpred_arr[i])) {
if (except_arr) {
- ARR_APP1(ir_node *, except_arr, cfgpred_arr[i]);
+ ARR_APP1(ir_node *, except_arr, cfgpred_arr[i]);
} else {
- except_arr = NEW_ARR_F(ir_node *, 1);
- except_arr[0] = cfgpred_arr[i];
+ except_arr = NEW_ARR_F(ir_node *, 1);
+ except_arr[0] = cfgpred_arr[i];
}
++n_except;
}
data->except = new_EndExcept();
/* mem */
for (i = n_except - 1; i >= 0; --i) {
- ir_node * node = skip_Proj(except_arr[i]);
- if (get_irn_op(node) == op_Call) {
- in[i] = new_r_Proj(irg, get_nodes_Block(node), node, mode_M, 3);
- } else if (get_irn_op(node) == op_Raise) {
- in[i] = new_r_Proj(irg, get_nodes_Block(node), node, mode_M, 1);
+ ir_node *node = skip_Proj(skip_Tuple(except_arr[i]));
+ ir_op *op = get_irn_op(node);
+ if (op == op_Call) {
+ in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_Call_M_except);
+ } else if (op == op_Raise) {
+ in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_Raise_M);
+ } else if (op == op_CopyB) {
+ in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_CopyB_M_except);
+ } else if (op == op_Bound) {
+ in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, pn_Bound_M_except);
} else {
- assert(is_fragile_op(node));
- /* We rely that all cfops have the memory output at the same position. */
- in[i] = new_r_Proj(irg, get_nodes_Block(node), node, mode_M, 0);
+ assert(is_fragile_op(node));
+ /* We rely that all cfops have the memory output at the same position. */
+ in[i] = new_r_Proj(irg, get_nodes_block(node), node, mode_M, 0);
}
}
data->except_mem = new_Phi(n_except, in, mode_M);
/* This Phi is a merge, therefor needs not be kept alive.
It might be optimized away, though. */
if (get_End_keepalive(end, get_End_n_keepalives(end)-1 )
- == data->except_mem)
+ == data->except_mem)
set_End_keepalive(end, get_End_n_keepalives(end)-1, new_Bad());
DEL_ARR_F(in);
}
/* Zwischengespeicherte Daten wieder freigeben. */
static void cleanup_irg(ir_graph * irg) {
- entity * ent = get_irg_ent(irg);
+ entity * ent = get_irg_entity(irg);
irg_data_t * data = get_entity_link(ent);
assert(data);
if (data->res) DEL_ARR_F(data->res);
static void move_phis(ir_node * from_block, ir_node * to_block) {
ir_node * phi;
for (phi = get_irn_link(from_block); phi != NULL; phi = get_irn_link(phi)) {
- set_nodes_Block(phi, to_block);
+ set_nodes_block(phi, to_block);
}
assert(get_irn_link(to_block) == NULL);
set_irn_link(to_block, get_irn_link(from_block));
/* Rekursiv die Operation "node" und alle ihre Vorgänger aus dem Block
- * "from_block" nach "to_block" verschieben. */
+ * "from_block" nach "to_block" verschieben.
+ * Verschiebe ebenfalls die Projs aus diesen Operationen. */
static void move_nodes(ir_node * from_block, ir_node * to_block, ir_node * node) {
- int i;
- for (i = get_irn_arity(node) - 1; i >= 0; --i) {
+ int i, arity = get_irn_arity(node);
+ ir_node *proj;
+
+ for (i = arity - 1; i >= 0; --i) {
ir_node * pred = get_irn_n(node, i);
- if (get_nodes_Block(pred) == from_block) {
+ if (get_nodes_block(pred) == from_block) {
move_nodes(from_block, to_block, pred);
}
}
- set_nodes_Block(node, to_block);
+ set_nodes_block(node, to_block);
+
+ /* Move projs of this node. */
+ proj = get_irn_link(node);
+ for (; proj; proj = skip_Id(get_irn_link(proj))) {
+ if (get_irn_op(proj) != op_Proj && get_irn_op(proj) != op_Filter) continue;
+ if ((get_nodes_block(proj) == from_block) && (skip_Proj(get_irn_n(proj, 0)) == node))
+ set_nodes_block(proj, to_block);
+ }
}
* Start-Block auf den Aufrufer hinzufügen. */
static void construct_start(entity * caller, entity * callee,
ir_node * call, ir_node * exec) {
- irg_data_t * data = get_entity_link(callee);
- ir_graph * irg = get_entity_irg(callee);
- ir_node * start = get_irg_start(irg), * filter;
+ irg_data_t *data = get_entity_link(callee);
+ ir_graph *irg = get_entity_irg(callee);
+ ir_node *start = get_irg_start(irg);
+ ir_node *filter;
assert(irg);
assert(get_entity_peculiarity(callee) == peculiarity_existent); /* Else data is not initalized. */
assert((0 <= data->count) &&
- (data->count < get_Block_cg_n_cfgpreds(get_nodes_Block(start))));
- set_Block_cg_cfgpred(get_nodes_Block(start), data->count, exec);
+ (data->count < get_Block_cg_n_cfgpreds(get_nodes_block(start))));
+
+ set_Block_cg_cfgpred(get_nodes_block(start), data->count, exec);
for (filter = get_irn_link(start); filter; filter = get_irn_link(filter)) {
if (get_irn_op(filter) != op_Filter) continue;
if (get_Proj_pred(filter) == start) {
switch ((int) get_Proj_proj(filter)) {
- case pns_global_store:
- set_Filter_cg_pred(filter, data->count, get_Call_mem(call));
- break;
- case pns_frame_base:
- /* "frame_base" wird nur durch Unknown dargestellt. Man kann ihn aber
- * auch explizit darstellen, wenn sich daraus Vorteile für die
- * Datenflussanalyse ergeben. */
- set_Filter_cg_pred(filter, data->count, new_Unknown());
- break;
- case pns_globals:
- /* "globals" wird nur durch Unknown dargestellt. Man kann ihn aber auch
- * explizit darstellen, wenn sich daraus Vorteile für die
- * Datenflussanalyse ergeben. */
- set_Filter_cg_pred(filter, data->count, new_Unknown());
- break;
+ case pn_Start_M:
+ set_Filter_cg_pred(filter, data->count, get_Call_mem(call));
+ break;
+ case pn_Start_P_frame_base:
+ /* "frame_base" wird nur durch Unknown dargestellt. Man kann ihn aber
+ * auch explizit darstellen, wenn sich daraus Vorteile für die
+ * Datenflussanalyse ergeben. */
+ set_Filter_cg_pred(filter, data->count, get_cg_Unknown(get_irn_mode(filter)));
+ break;
+ case pn_Start_P_globals:
+ /* "globals" wird nur durch Unknown dargestellt. Man kann ihn aber auch
+ * explizit darstellen, wenn sich daraus Vorteile für die
+ * Datenflussanalyse ergeben. */
+ set_Filter_cg_pred(filter, data->count, get_cg_Unknown(get_irn_mode(filter)));
+ break;
default:
- /* not reached */
- assert(0 && "not reached");
- break;
+ /* not reached */
+ assert(0 && "not reached");
+ break;
}
} else {
set_Filter_cg_pred(filter, data->count, get_Call_param(call, get_Proj_proj(filter)));
in[i] = new_Bad();
}
} else { /* unknown */
- in[i] = new_Unknown();
+ in[i] = get_cg_Unknown(mode_M);
}
}
}
in[i] = new_Bad();
}
} else { /* unknown */
- in[i] = new_Unknown();
+ in[i] = get_cg_Unknown(mode_M);
}
}
}
/* Abhängigkeiten für ein Ergebnis über alle aufgerufenen Methoden
* bestimmen. */
-static void fill_result(int pos, int length, irg_data_t * data[], ir_node * in[]) {
+static void fill_result(int pos, int length, irg_data_t * data[], ir_node * in[], ir_mode *m) {
int i;
for (i = 0; i < length; ++i) {
if (data[i]) { /* explicit */
in[i] = new_Bad();
}
} else { /* unknown */
- in[i] = new_Unknown();
+ in[i] = get_cg_Unknown(m);
}
}
}
/* Returns true if only caller of irg is "Unknown". */
static bool is_outermost_graph(ir_graph *irg) {
- irg_data_t * data = get_entity_link(get_irg_ent(irg));
+ irg_data_t * data = get_entity_link(get_irg_entity(irg));
if (data->count) {
return false;
} else if (data->open) {
* Methoden auf die CallBegin-Operation, und von der Aufrufstelle auf die
* aufgerufenen Methoden eintragen. */
static void construct_call(ir_node * call) {
- int n_callees = get_Call_n_callees(call);
- ir_node * post_block = get_nodes_Block(call); /* block nach dem Aufruf */
- ir_node * pre_block = create_Block(get_Block_n_cfgpreds(post_block),
- get_Block_cfgpred_arr(post_block)); /* block vor dem Aufruf (mit CallBegin) */
- ir_node * except_block = NULL, * proj;
- ir_node * jmp = new_Break(); /* Sprung für intraprozedurale Darstellung (in
- * pre_block) */
- ir_node * call_begin = new_CallBegin(call); /* (in pre_block) */
- ir_node ** in = NEW_ARR_F(ir_node *, n_callees);
- entity * caller = get_irg_ent(current_ir_graph); /* entity des aktuellen ir_graph */
- entity ** callees = NEW_ARR_F(entity *, n_callees); /* aufgerufene Methoden: entity */
- ir_graph ** irgs = NEW_ARR_F(ir_graph *, n_callees); /* aufgerufene Methoden: ir_graph */
- irg_data_t ** data = NEW_ARR_F(irg_data_t *, n_callees); /* aufgerufene Methoden: irg_data_t */
- int i;
+ int i, n_callees;
+ ir_node *post_block, *pre_block, *except_block, * proj, *jmp, *call_begin;
+ ir_node ** in;
+ entity * caller;
+ entity ** callees;
+ ir_graph ** irgs;
+ irg_data_t ** data;
+
+ n_callees = get_Call_n_callees(call);
+ post_block = get_nodes_block(call); /* block nach dem Aufruf */
+ pre_block = create_Block(get_Block_n_cfgpreds(post_block),
+ get_Block_cfgpred_arr(post_block)); /* block vor dem Aufruf (mit CallBegin) */
+ except_block = NULL;
+ jmp = new_Break(); /* Sprung für intraprozedurale Darstellung (in * pre_block) */
+ call_begin = new_CallBegin(call); /* (in pre_block) */
+ /* CallBegin might be entry to endless recursion. */
+ add_End_keepalive(get_irg_end(get_irn_irg(pre_block)), pre_block);
+
+ in = NEW_ARR_F(ir_node *, n_callees);
+ caller = get_irg_entity(current_ir_graph); /* entity des aktuellen ir_graph */
+ callees = NEW_ARR_F(entity *, n_callees); /* aufgerufene Methoden: entity */
+ irgs = NEW_ARR_F(ir_graph *, n_callees); /* aufgerufene Methoden: ir_graph */
+ data = NEW_ARR_F(irg_data_t *, n_callees); /* aufgerufene Methoden: irg_data_t */
/* post_block kann bereits interprozedurale Steuerflussvorgänger
* besitzen. Diese müssen dann auch noch für den pre_block gesetzt werden. */
if (get_Block_cg_cfgpred_arr(post_block)) {
set_Block_cg_cfgpred_arr(pre_block, get_Block_cg_n_cfgpreds(post_block),
- get_Block_cg_cfgpred_arr(post_block));
+ get_Block_cg_cfgpred_arr(post_block));
remove_Block_cg_cfgpred_arr(post_block);
}
/* Operationen verschieben */
move_phis(post_block, pre_block);
move_nodes(post_block, pre_block, call);
- /* @@@ GL Wer setzt die Laenge des PostBlock cgfpred array auf 1?
- GL: na, dieser Befehl... generiert neuen array. */
set_irn_in(post_block, 1, &jmp);
/* Wiederverwendete Daten initialisieren. */
for (i = 0; i < n_callees; ++i) {
callees[i] = get_Call_callee(call, i);
- irgs[i] = callees[i] ? get_entity_irg(callees[i]) : NULL;
+ irgs[i] = get_entity_irg(callees[i]);
data[i] = get_entity_link(callees[i]);
+ /* Only entities that have an irg got a irg_data data structure.
+ In others there is some arbitrary garbage in the link field. */
+ if (!irgs[i]) { assert(!data[i]); data[i] = NULL; }
}
/*
for (i = 0; i < n_callees; ++i) {
if (data[i]) { /* explicit */
if (data[i]->reg) {
- in[i] = new_r_Proj(irgs[i], get_nodes_Block(data[i]->reg),
- data[i]->reg, mode_X, data[i]->count);
+ in[i] = new_r_Proj(irgs[i], get_nodes_block(data[i]->reg),
+ data[i]->reg, mode_X, data[i]->count);
} else {
- in[i] = new_Bad();
+ in[i] = new_Bad();
}
} else { /* unknown */
- in[i] = new_Unknown();
+ in[i] = get_cg_Unknown(mode_X);
}
}
set_interprocedural_view(0);
if ((proj = get_except(call)) != NULL) {
int preds = 0;
bool exc_to_end = false;
-#if 1
if (exc_branches_to_end(current_ir_graph, proj)) {
/* The Call aborts the procedure if it returns with an exception.
If this is an outermost procedure, the normal handling of exceptions
Frim. So directly branch to the end block with all exceptions. */
exc_to_end = true;
if (is_outermost_graph(current_ir_graph)) {
- except_block = get_irg_end_block(current_ir_graph);
+ except_block = get_irg_end_block(current_ir_graph);
} else {
- irg_data_t * data = get_entity_link(get_irg_ent(current_ir_graph));
- except_block = get_nodes_block(data->except);
+ irg_data_t * tmp_data = get_entity_link(get_irg_entity(current_ir_graph));
+ except_block = get_nodes_block(tmp_data->except);
}
- } else
-#endif
- {
+ } else {
except_block = create_Block(1, &proj);
- set_nodes_Block(proj, except_block);
+ set_nodes_block(proj, except_block);
exchange(proj, new_Break());
set_irg_current_block(current_ir_graph, pre_block);
- set_irn_n(except_block, 0, new_Proj(call, mode_X, 1));
+ set_irn_n(except_block, 0, new_Proj(call, mode_X, pn_Call_X_except));
set_irg_current_block(current_ir_graph, post_block);
}
for (i = 0; i < n_callees; ++i) {
entity * callee = get_Call_callee(call, i);
if (data[i]) { /* explicit */
- if (data[i]->except) {
- in[i] = new_r_Proj(get_entity_irg(callee), get_nodes_Block(data[i]->except),
- data[i]->except, mode_X, data[i]->count);
- } else {
- in[i] = new_Bad();
- }
+ if (data[i]->except) {
+ in[i] = new_r_Proj(get_entity_irg(callee), get_nodes_block(data[i]->except),
+ data[i]->except, mode_X, data[i]->count);
+ } else {
+ in[i] = new_Bad();
+ }
} else { /* unknown */
- in[i] = new_Unknown();
+ in[i] = get_cg_Unknown(mode_X);
}
}
/* append all existing preds of the end block to new in array.
* Normal access routine guarantees that with first visit we
* get the normal preds, and from then on the _cg_ preds.
- * (interporcedural view is set!)
+ * (interprocedural view is set!)
* Do not add the exc pred of end we are replacing! */
for (i = get_Block_n_cfgpreds(except_block)-1; i >= 0; --i) {
- ir_node *pred = get_Block_cfgpred(except_block, i);
- if (pred != proj) {
- ARR_APP1(ir_node *, in, pred);
- preds++;
- }
+ ir_node *pred = get_Block_cfgpred(except_block, i);
+ if (pred != proj) {
+ ARR_APP1(ir_node *, in, pred);
+ preds++;
+ }
}
}
set_Block_cg_cfgpred_arr(except_block, preds, in);
* eintragen. */
set_irg_current_block(current_ir_graph, pre_block);
for (i = 0; i < n_callees; ++i) {
- construct_start(caller, callees[i], call, new_Proj(call_begin, mode_X, i));
+ if (irgs[i]) /* Else there is not graph to call */
+ construct_start(caller, callees[i], call, new_Proj(call_begin, mode_X, i));
}
/* Proj-Operationen in Filter-Operationen umwandeln und
* interprozedurale Vorgänger einfügen. */
set_irg_current_block(current_ir_graph, post_block);
- for (proj = get_irn_link(call); proj && get_irn_op(proj) == op_Proj; proj = get_irn_link(proj)) {
+ for (proj = get_irn_link(call); proj; proj = get_irn_link(proj)) {
+ if (get_irn_op(proj) != op_Proj) continue;
+ if (skip_Proj(get_Proj_pred(proj)) != call) continue;
if (get_Proj_pred(proj) == call) {
- if (get_Proj_proj(proj) == 0) { /* memory */
- /* memory */
- ir_node * filter = exchange_proj(proj);
- /* filter in die Liste der Phis aufnehmen */
- if (get_irn_link(filter) == NULL) { /* note CSE */
- set_irn_link(filter, get_irn_link(post_block));
- set_irn_link(post_block, filter);
- }
- fill_mem(n_callees, data, in);
- set_Filter_cg_pred_arr(filter, n_callees, in);
- } else if (get_Proj_proj(proj) == 1) { /* except */
- /* nothing: siehe oben */
- } else if (get_Proj_proj(proj) == 2) { /* results */
- set_nodes_Block(proj, pre_block);
- } else if (get_Proj_proj(proj) == 3) { /* except_mem */
- /* except_mem */
- ir_node * filter;
- assert(except_block);
- set_irg_current_block(current_ir_graph, except_block);
- filter = exchange_proj(proj);
- /* filter in die Liste der Phis aufnehmen */
- if (get_irn_link(filter) == NULL) { /* note CSE */
- set_irn_link(filter, get_irn_link(except_block));
- set_irn_link(except_block, filter);
- }
- set_irg_current_block(current_ir_graph, post_block);
- fill_except_mem(n_callees, data, in);
- set_Filter_cg_pred_arr(filter, n_callees, in);
+ if (get_Proj_proj(proj) == pn_Call_M_regular) { /* memory */
+ ir_node * filter;
+
+ set_nodes_block(proj, post_block);
+ filter = exchange_proj(proj);
+ /* filter in die Liste der Phis aufnehmen */
+ if (get_irn_link(filter) == NULL) { /* note CSE */
+ set_irn_link(filter, get_irn_link(post_block));
+ set_irn_link(post_block, filter);
+ }
+ fill_mem(n_callees, data, in);
+ set_Filter_cg_pred_arr(filter, n_callees, in);
+ } else if (get_Proj_proj(proj) == pn_Call_X_except) { /* except */
+ /* nothing: siehe oben */
+ } else if (get_Proj_proj(proj) == pn_Call_T_result) { /* results */
+ /* nothing */
+ } else if (get_Proj_proj(proj) == pn_Call_M_except) { /* except_mem */
+ ir_node * filter;
+
+ set_nodes_block(proj, post_block);
+ assert(except_block);
+ set_irg_current_block(current_ir_graph, except_block);
+ filter = exchange_proj(proj);
+ /* filter in die Liste der Phis aufnehmen */
+ if (get_irn_link(filter) == NULL) { /* note CSE */
+ set_irn_link(filter, get_irn_link(except_block));
+ set_irn_link(except_block, filter);
+ }
+ set_irg_current_block(current_ir_graph, post_block);
+ fill_except_mem(n_callees, data, in);
+ set_Filter_cg_pred_arr(filter, n_callees, in);
} else {
- assert(0 && "not reached");
+ assert(0 && "not reached");
}
- } else {
- /* result */
- ir_node * filter = exchange_proj(proj);
+ } else { /* result */
+ ir_node * filter;
+
+ assert(is_Proj(get_Proj_pred(proj)) && get_Proj_pred(get_Proj_pred(proj)) == call);
+ set_nodes_block(proj, post_block);
+ filter = exchange_proj(proj);
/* filter in die Liste der Phis aufnehmen */
- if (get_irn_link(filter) == NULL) { /* note CSE */
- set_irn_link(filter, get_irn_link(post_block));
- set_irn_link(post_block, filter);
+ if (get_irn_link(filter) == NULL) { /* not CSE */
+ set_irn_link(filter, get_irn_link(post_block));
+ set_irn_link(post_block, filter);
}
- fill_result(get_Proj_proj(filter), n_callees, data, in);
+ fill_result(get_Proj_proj(filter), n_callees, data, in, get_irn_mode(filter));
set_Filter_cg_pred_arr(filter, n_callees, in);
}
}
void cg_construct(int arr_len, entity ** free_methods_arr) {
int i;
+ if (get_irp_ip_view_state() == ip_view_valid) return;
+ if (get_irp_ip_view_state() == ip_view_invalid) cg_destruct();
+ set_irp_ip_view(ip_view_valid);
+
collect_phicallproj();
/* count callers */
/* prepare irgs */
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph * irg = get_irp_irg(i);
- entity * ent = get_irg_ent(irg);
+ entity * ent = get_irg_entity(irg);
irg_data_t * data = get_entity_link(ent);
if (data->count) {
prepare_irg(irg, data);
/* construct calls */
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_node * node;
+
current_ir_graph = get_irp_irg(i);
for (node = get_irn_link(get_irg_end(current_ir_graph)); node; node = get_irn_link(node)) {
if (get_irn_op(node) == op_Call) {
- int n_callees = get_Call_n_callees(node);
- if (n_callees > 1 || (n_callees == 1 && get_Call_callee(node, 0) != NULL)) {
- construct_call(node);
- }
+ int j, n_callees = get_Call_n_callees(node);
+ for (j = 0; j < n_callees; ++j)
+ if (get_entity_irg(get_Call_callee(node, j)))
+ break;
+ if (j < n_callees) /* There is an entity with a graph */
+ construct_call(node);
}
}
}
static void destruct_walker(ir_node * node, void * env) {
if (get_irn_op(node) == op_Block) {
remove_Block_cg_cfgpred_arr(node);
+ /* Do not turn Break into Jmp. Better: merge blocks right away.
+ Well, but there are Breaks left.
+ See exc1 from ajacs-rts/Exceptions.java. */
+ if (get_Block_n_cfgpreds(node) == 1) {
+ ir_node *pred = get_Block_cfgpred(node, 0);
+ if (get_irn_op(pred) == op_Break)
+ exchange(node, get_nodes_block(pred));
+ }
} else if (get_irn_op(node) == op_Filter) {
- set_irg_current_block(current_ir_graph, get_nodes_Block(node));
+ set_irg_current_block(current_ir_graph, get_nodes_block(node));
exchange(node, new_Proj(get_Filter_pred(node), get_irn_mode(node), get_Filter_proj(node)));
} else if (get_irn_op(node) == op_Break) {
- set_irg_current_block(current_ir_graph, get_nodes_Block(node));
+ set_irg_current_block(current_ir_graph, get_nodes_block(node));
exchange(node, new_Jmp());
} else if (get_irn_op(node) == op_Call) {
remove_Call_callee_arr(node);
+ } else if (get_irn_op(node) == op_Proj) {
+ /* some ProjX end up in strange blocks. */
+ set_nodes_block(node, get_nodes_block(get_Proj_pred(node)));
}
}
void cg_destruct(void) {
int i;
- for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- ir_graph * irg = get_irp_irg(i);
- irg_walk_graph(irg, destruct_walker, clear_link, NULL);
- set_irg_frame(irg, skip_nop(get_irg_frame(irg)));
- set_irg_globals(irg, skip_nop(get_irg_globals(irg)));
+ if (get_irp_ip_view_state() != ip_view_no) {
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
+ ir_graph * irg = get_irp_irg(i);
+ irg_walk_graph(irg, destruct_walker, firm_clear_link, NULL);
+
+ set_irg_frame (irg, skip_Id(get_irg_frame(irg)));
+ set_irg_globals (irg, skip_Id(get_irg_globals(irg)));
+ set_irg_initial_mem(irg, skip_Id(get_irg_initial_mem(irg)));
+ set_irg_end_reg (irg, get_irg_end(irg));
+ set_irg_end_except (irg, get_irg_end(irg));
+
+ set_irg_callee_info_state(irg, irg_callee_info_none);
+ }
+
+ set_irp_ip_view(ip_view_no);
}
}