Commit fb648cf1 authored by Götz Lindenmaier's avatar Götz Lindenmaier
Browse files

minor changes to help with making the ajacs-jikes backend

more general.

[r313]
parent f5d8d4c4
......@@ -10,14 +10,6 @@
/* $Id$ */
#define DDMSG2(X) printf("%s(l.%i) %s%s: %ld\n", __FUNCTION__, __LINE__, \
id_to_str(get_irn_opident(X)), id_to_str(get_irn_modeident(X)), \
get_irn_node_nr(X))
#define DDMSG5(X) printf("%s%s: %ld", \
id_to_str(get_irn_opident(X)), id_to_str(get_irn_modeident(X)), \
get_irn_node_nr(X))
#include "irouts.h"
#include "irnode_t.h"
#include "irgraph_t.h" /* To access irg->outs field (which is private to this module)
......
......@@ -57,17 +57,6 @@ typedef enum {
k_ir_node
} firm_kind;
#if 0
k_type_class,
k_type_strct,
k_type_method,
k_type_union,
k_type_array,
k_type_enumeration,
k_type_pointer,
k_type_primitive,
#endif
/* returns the kind of the thing */
firm_kind get_kind(void *firm_thing);
......
......@@ -98,9 +98,12 @@ id_init (void)
#if 1
inline ident *id_from_str (char *str, int len) {
inline ident *id_from_str (const char *str, int len) {
assert (len > 0);
return (const set_entry *)set_hinsert (id_set, (str), (len), ID_HASH ((str), (len)));
return (const set_entry *) set_hinsert (id_set,
(str),
(len),
ID_HASH ((str), (len)));
}
inline const char *id_to_str (ident *id) {
......@@ -110,5 +113,25 @@ inline const char *id_to_str (ident *id) {
inline int id_to_strlen(ident *id) {
return ((id)->size);
}
#endif
int id_is_prefix (ident *prefix, ident *id) {
int i;
if (id_to_strlen(prefix) > id_to_strlen(id)) return 0;
if (0 == memcmp(&(prefix->dptr[0]), &(id->dptr[0]), id_to_strlen(prefix)))
return 1;
return 0;
}
int id_is_suffix (ident *suffix, ident *id) {
int suflen = id_to_strlen(suffix);
int idlen = id_to_strlen(id);
char *part;
if (suflen > idlen) return 0;
part = (char *) &id->dptr[0];
part = part + (idlen - suflen);
if (0 == memcmp(&(suffix->dptr[0]), part, suflen))
return 1;
return 0;
}
......@@ -20,7 +20,7 @@
* ident -- identifiers in the firm library
* NOTES
* Identifiers are used in the firm library. This is the interface to it.
*
* @@@ we need comparison of the prefis of two idents! (strncmp);
******
*/
......@@ -51,7 +51,7 @@ typedef const struct set_entry ident;
* id_to_str, id_to_strlen
***
*/
inline ident *id_from_str (char *str, int len);
inline ident *id_from_str (const char *str, int len);
/****f* ident/id_to_str
*
......@@ -88,6 +88,43 @@ inline const char *id_to_str (ident *id);
* id_from_str, id_to_str
***
*/
inline int id_to_strlen(ident *id);
inline int id_to_strlen(ident *id);
/****f* ident/id_is_suffix
*
* NAME
*
* SYNOPSIS
* int id_is_prefix (ident *prefix, ident *id);
* FUNCTION
* Returns true if prefix is prefix of id.
* INPUTS
* prefix - the prefix
* id - the ident
* SEE ALSO
* id_from_str, id_to_str, id_is_prefix
***
*/
/* */
int id_is_prefix (ident *prefix, ident *id);
/****f* ident/id_is_suffix
*
* NAME
*
* SYNOPSIS
* int id_is_suffix (ident *suffix, ident *id);
* FUNCTION
* Returns true if suffix is suffix of id.
* INPUTS
* suffix - the suffix
* id - the ident
* SEE ALSO
* id_from_str, id_to_str, id_is_prefix
***
*/
/* */
int id_is_suffix (ident *suffix, ident *id);
# endif /* _IDENT_H_ */
......@@ -1134,20 +1134,22 @@ get_r_frag_value_internal (ir_node *block, ir_node *cfOp, int pos, ir_mode *mode
if (!res) {
if (block->attr.block.graph_arr[pos]) {
/* There was a set_value after the cfOp and no get_value before that
set_value. We must build a Phi node now. */
set_value. We must build a Phi node now. */
if (block->attr.block.matured) {
int ins = get_irn_arity(block);
ir_node **nin;
NEW_ARR_A (ir_node *, nin, ins);
res = phi_merge(block, pos, mode, nin, ins);
int ins = get_irn_arity(block);
ir_node **nin;
NEW_ARR_A (ir_node *, nin, ins);
res = phi_merge(block, pos, mode, nin, ins);
} else {
res = new_r_Phi0 (current_ir_graph, block, mode);
res->attr.phi0_pos = pos;
res->link = block->link;
block->link = res;
res = new_r_Phi0 (current_ir_graph, block, mode);
res->attr.phi0_pos = pos;
res->link = block->link;
block->link = res;
}
assert(res);
/* It's a Phi, we can write this into all graph_arrs with NULL */
assert(res);
/* @@@ tested by Flo: set_frag_value(frag_arr, pos, res);
but this should be better: (remove comment if this works) */
/* It's a Phi, we can write this into all graph_arrs with NULL */
set_frag_value(block->attr.block.graph_arr, pos, res);
} else {
res = get_r_value_internal(block, pos, mode);
......@@ -1169,7 +1171,6 @@ phi_merge (ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins)
ir_node *prevBlock, *prevCfOp, *res, *phi0;
int i;
/* If this block has no value at pos create a Phi0 and remember it
in graph_arr to break recursions.
Else we may not set graph_arr as there a later value is remembered. */
......@@ -1193,11 +1194,13 @@ phi_merge (ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins)
/* We don't need to care about exception ops in the start block.
There are none by definition. */
return block->attr.block.graph_arr[pos];
} else {
} else {
phi0 = new_r_Phi0(current_ir_graph, block, mode);
block->attr.block.graph_arr[pos] = phi0;
#if PRECISE_EXC_CONTEXT
/* Set graph_arr for fragile ops. Also here we should break recursion. */
/* Set graph_arr for fragile ops. Also here we should break recursion.
We could choose a cyclic path through an cfop. But the recursion would
break at some point. */
set_frag_value(block->attr.block.graph_arr, pos, phi0);
#endif
}
......@@ -1220,12 +1223,11 @@ phi_merge (ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins)
if (!is_Bad(prevBlock)) {
#if PRECISE_EXC_CONTEXT
if (is_fragile_op(prevCfOp) && (get_irn_op (prevCfOp) != op_Bad)) {
assert(get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode));
nin[i-1] = get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode);
} else
assert(get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode));
nin[i-1] = get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode);
} else
#endif
nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
} else {
nin[i-1] = new_Bad();
}
......@@ -1362,9 +1364,10 @@ mature_block (ir_node *block)
if (!get_Block_matured(block)) {
/* an in-array for phi-merge with same size. */
/* An array for building the Phi nodes. */
ins = ARR_LEN (block->in)-1;
NEW_ARR_A (ir_node *, nin, ins);
/* shouldn't we delete this array at the end of the procedure? @@@ memory leak? */
/* Traverse a chain of Phi nodes attached to this block and mature
these, too. **/
......@@ -1477,7 +1480,8 @@ new_Quot (ir_node *memop, ir_node *op1, ir_node *op2)
res = new_r_Quot (current_ir_graph, current_ir_graph->current_block,
memop, op1, op2);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1490,7 +1494,8 @@ new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2)
res = new_r_DivMod (current_ir_graph, current_ir_graph->current_block,
memop, op1, op2);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1503,7 +1508,8 @@ new_Div (ir_node *memop, ir_node *op1, ir_node *op2)
res = new_r_Div (current_ir_graph, current_ir_graph->current_block,
memop, op1, op2);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1516,7 +1522,8 @@ new_Mod (ir_node *memop, ir_node *op1, ir_node *op2)
res = new_r_Mod (current_ir_graph, current_ir_graph->current_block,
memop, op1, op2);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1612,7 +1619,8 @@ new_Call (ir_node *store, ir_node *callee, int arity, ir_node **in,
res = new_r_Call (current_ir_graph, current_ir_graph->current_block,
store, callee, arity, in, type);
#if PRECISE_EXC_CONTEXT
res->attr.call.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.call.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1639,7 +1647,8 @@ new_Load (ir_node *store, ir_node *addr)
res = new_r_Load (current_ir_graph, current_ir_graph->current_block,
store, addr);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1652,7 +1661,8 @@ new_Store (ir_node *store, ir_node *addr, ir_node *val)
res = new_r_Store (current_ir_graph, current_ir_graph->current_block,
store, addr, val);
#if PRECISE_EXC_CONTEXT
res->attr.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.frag_arr = new_frag_arr(res);
#endif
return res;
......@@ -1666,7 +1676,8 @@ new_Alloc (ir_node *store, ir_node *size, type *alloc_type,
res = new_r_Alloc (current_ir_graph, current_ir_graph->current_block,
store, size, alloc_type, where);
#if PRECISE_EXC_CONTEXT
res->attr.a.frag_arr = new_frag_arr(res);
if (current_ir_graph->phase_state == phase_building)
res->attr.a.frag_arr = new_frag_arr(res);
#endif
return res;
......
......@@ -590,6 +590,13 @@
* size The symbolic constant represents the size of a class.
* link_info Information for the linker, e.g. the name of a global
* variable.
* To represent a pointer to an entity that is represented by an entity
* datastructure don't use
* new_SymConst((type_or_id*)get_entity_ld_ident(ent), linkage_ptr_info);.
* Use a real const instead:
* new_Const(mode_p, tarval_p_from_entity(ent));
* This makes the Constant independent of name changes of the entity due to
* mangling.
*
* Parameters
* kind The kind of the symbolic constant: type_tag, size or link_info.
......
......@@ -18,7 +18,7 @@
# include "irdump.h"
# include "panic.h"
# include <string.h>
# include "entity.h"
# include "entity_t.h"
# include <stdlib.h>
# include "array.h"
# include "irop_t.h"
......@@ -102,11 +102,11 @@ dump_node_opcode (ir_node *n)
/* SymConst */
} else if (n->op->code == iro_SymConst) {
if (get_SymConst_kind(n) == linkage_ptr_info) {
xfprintf (F, "%I", get_SymConst_ptrinfo(n));
xfprintf (F, "SymC %I", get_SymConst_ptrinfo(n));
} else {
assert(get_kind(get_SymConst_type(n)) == k_type);
assert(get_type_ident(get_SymConst_type(n)));
xfprintf (F, "%s ", id_to_str(get_type_ident(get_SymConst_type(n))));
xfprintf (F, "SymC %I ", get_type_ident(get_SymConst_type(n)));
if (get_SymConst_kind == type_tag)
xfprintf (F, "tag");
else
......@@ -644,8 +644,9 @@ dump_type_info (type_or_ent *tore, void *env) {
}
xfprintf(F, "\"}\n");
/* The Edges */
/* skip this to reduce graph. Member edge of type is parallel to this edge. *
xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));
ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
xfprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
ENT_TYPE_EDGE_ATTR "}\n", ent, get_entity_type(ent));
for(i = 0; i < get_entity_n_overwrites(ent); i++)
......@@ -760,7 +761,8 @@ void vcg_open (ir_graph *irg, char *suffix) {
/** open file for vcg graph */
ent = get_irg_ent(irg);
id = get_entity_ld_ident (ent);
id = ent->ld_name ? ent->ld_name : ent->name;
/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
len = id_to_strlen (id);
cp = id_to_str (id);
fname = malloc (len + 5 + strlen(suffix));
......@@ -1135,11 +1137,11 @@ void dump_all_ir_graphs (void dump_graph(ir_graph*)) {
/* To turn off display of edge labels. Edge labels offen cause xvcg to
abort with a segmentation fault. */
void turn_of_edge_labels() {
void turn_off_edge_labels() {
edge_label = 0;
}
void dump_constant_entity_values() {
void turn_off_constant_entity_values() {
const_entities = 0;
}
......
......@@ -220,9 +220,9 @@ void dump_all_ir_graphs (void dump_graph(ir_graph*));
/****m* irdump/turn_of_edge_labels
*
* NAME
* turn_of_edge_labels
* turn_off_edge_labels
* SYNOPSIS
* void turn_of_edge_labels();
* void turn_off_edge_labels();
* FUNCTION
* Sets the vcg flag "display_edge_labels" to no. This is necessary
* as xvcg and aisee both fail to display graphs with self-edges if these
......@@ -235,15 +235,15 @@ void dump_all_ir_graphs (void dump_graph(ir_graph*));
*
***
*/
void turn_of_edge_labels();
void turn_off_edge_labels();
/****m* irdump/dump_constant_entity_values
/****m* irdump/turn_off_constant_entity_values
*
* NAME
* dump_constant_entity_values
* turn_off_constant_entity_values
* SYNOPSIS
* void dump_constant_entity_values()
* void turn_off_constant_entity_values()
* FUNCTION
* Turns off dumping the values of constant entities. Makes type graphs
* better readable.
......@@ -254,10 +254,10 @@ void turn_of_edge_labels();
*
***
*/
void dump_constant_entity_values();
void turn_off_constant_entity_values();
/****m* irdump/dump_constant_entity_values
/****m* irdump/dump_keepalive_edges
*
* NAME
* dump_keepalive_edges
......
......@@ -21,7 +21,7 @@ void local_optimize_graph (ir_graph *irg);
inputs to Phi nodes.
The graph may not be in state phase_building. The outs datasturcture
is freed, the outs state set to no_outs. (@@@ Change this? -> inconsistent.)
Removes old attributes of nodes.
Removes old attributes of nodes. Sets link field to NULL.
Attention: the numbers assigned to nodes if the library is compiled for
development/debugging are not conserved by copying. */
void dead_node_elimination(ir_graph *irg);
......
......@@ -88,7 +88,8 @@ new_ir_graph (entity *ent, int n_loc)
/** A type that represents the stack frame. A class type so that it can
contain "inner" methods as in Pascal. **/
res->frame_type = new_type_class(mangle(get_entity_ident(ent), id_from_str("frame_tp", 8)));
res->frame_type = new_type_class(mangle(get_entity_ident(ent),
id_from_str(FRAME_TP_SUFFIX, strlen(FRAME_TP_SUFFIX))));
/** Nodes needed in every graph **/
res->end_block = new_immBlock ();
......@@ -330,6 +331,15 @@ set_irg_frame_type (ir_graph *irg, type *ftp)
irg->frame_type = ftp;
}
/* To test for a frame type */
int
is_frame_type(type *ftp) {
return ((is_class_type(ftp) || is_struct_type(ftp)) &&
id_is_suffix(id_from_str(FRAME_TP_SUFFIX, strlen(FRAME_TP_SUFFIX)),
get_type_ident(ftp)));
}
int
get_irg_n_loc (ir_graph *irg)
{
......@@ -343,7 +353,11 @@ get_irg_n_loc (ir_graph *irg)
void
set_irg_n_loc (ir_graph *irg, int n_loc)
{
irg->n_loc = n_loc;
#if PRECISE_EXC_CONTEXT
irg->n_loc = n_loc + 1 + 1;
#else
irg->n_loc = n_loc + 1;
#endif
}
irg_phase_state get_irg_phase_state (ir_graph *irg) {
......
......@@ -127,6 +127,8 @@ void set_irg_ent (ir_graph *irg, entity *ent);
type *get_irg_frame_type (ir_graph *irg);
void set_irg_frame_type (ir_graph *irg, type *ftp);
/* To test for a frame type */
int is_frame_type(type *ftp);
/* Use not encouraged, internal of Phi construction algorithm. */
int get_irg_n_loc (ir_graph *irg);
......@@ -141,12 +143,13 @@ void set_irg_n_loc (ir_graph *irg, int n_loc);
information associated with the graph. Optimizations invalidate these
states. */
/* state: phase
values: phase_building, phase_high, phase_low
The irg is in phase_building during construction of the irgraph.
It is in phase_high after construction. All nodes are allowed.
To get the irgraph into phase_low all Sel nodes must be removed
and replaced by explicit address computations. @@@ More conditions? */
/* state: phase values: phase_building, phase_high, phase_low.
The irg is in phase_building during construction of the irgraph. It is in
phase_high after construction. All nodes are allowed. To get the irgraph
into phase_low all Sel nodes must be removed and replaced by explicit
address computations. SymConst size and typetag nodes must be removed (@@@
really?). Initialization of memory allocated by Alloc must be explicit.
@@@ More conditions? */
typedef enum {
phase_building,
phase_high,
......
......@@ -14,6 +14,8 @@
# include "pset.h"
# include "irgraph.h"
#define FRAME_TP_SUFFIX "frame_tp"
/* ir_graph holds all information for a procedure */
struct ir_graph {
/** Basics of the representation **/
......
......@@ -16,7 +16,7 @@
# include "irnode.h"
# include "irgraph.h" /* visited flag */
# include "irprog.h"
void irg_walk_2(ir_node *node,
void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
......@@ -67,6 +67,26 @@ void irg_walk(ir_node *node,
/***************************************************************************/
/* Executes irg_walk(end, pre, post, env) for all irgraphs in irprog.
Sets current_ir_graph properly for each walk. Conserves current
current_ir_graph. */
void all_irg_walk(void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
void *env) {
int i;
ir_graph *irg, *rem;
rem = current_ir_graph;
for (i = 0; i < get_irp_n_irgs(); i++) {
irg = get_irp_irg(i);
current_ir_graph = irg;
irg_walk(get_irg_end(irg), pre, post, env);
}
current_ir_graph = rem;
}
/***************************************************************************/
/* Walks back from n until it finds a real cf op. */
ir_node *get_cf_op(ir_node *n) {
ir_node *pred;
......
......@@ -29,6 +29,13 @@ void irg_walk(ir_node *node,
void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
void *env);
/* Executes irg_walk(end, pre, post, env) for all irgraphs in irprog.
Sets current_ir_graph properly for each walk. Conserves current
current_ir_graph. */
void all_irg_walk(void (pre)(ir_node*, void*), void (post)(ir_node*, void*),
void *env);
/* Walks only over Block nodes in the graph. Has it's own visited
flag, so that it can be interleaved with the other walker. */
void irg_block_walk(ir_node *node,
......
......@@ -27,6 +27,7 @@
#define CALL_PARAM_OFFSET 2
#define SEL_INDEX_OFFSET 2
#define RETURN_RESULT_OFFSET 1 /* mem is not a result */
#define END_KEEPALIVE_OFFSET 0
static char *pnc_name_arr [] = {"False", "Eq", "Lt", "Le",
"Gt", "Ge", "Lg", "Leg", "Uo",
......@@ -300,6 +301,13 @@ set_irn_visited (ir_node *node, unsigned long visited)
assert (node);
node->visited = visited;
}
inline void
mark_irn_visited (ir_node *node) {
assert (node);
node->visited = current_ir_graph->visited;
}
inline void
set_irn_link (ir_node *node, ir_node *link) {
assert (node);
......@@ -471,6 +479,18 @@ set_Block_graph_arr (ir_node *node, int pos, ir_node *value) {
node->attr.block.graph_arr[pos+1] = value;
}
inline int
get_End_n_keepalives(ir_node *end) {
assert (end->op == op_End);
return (get_irn_arity(end) - END_KEEPALIVE_OFFSET);
}
inline ir_node *
get_End_keepalive(ir_node *end, int pos) {
assert (end->op == op_End);
return get_irn_n(end, pos + END_KEEPALIVE_OFFSET);
}
inline void
add_End_keepalive (ir_node *end, ir_node *ka) {
assert (end->op == op_End);
......@@ -796,6 +816,7 @@ get_Call_n_params (ir_node *node) {
inline int
get_Call_arity (ir_node *node) {
assert (node->op == op_Call);
return get_Call_n_params(node);
}
......
......@@ -91,6 +91,8 @@ inline ident *get_irn_opident (ir_node *node);
inline const char *get_irn_opname (ir_node *node);
inline void set_irn_visited (ir_node *node, unsigned long visited);
inline unsigned long get_irn_visited (ir_node *node);
/* Sets visited to get_irg_visited(current_ir_graph) */
inline void mark_irn_visited (ir_node *node);
inline void set_irn_link (ir_node *node, ir_node *link);
inline ir_node *get_irn_link (ir_node *node);
#ifdef DEBUG_libfirm
......@@ -149,9 +151,11 @@ inline ir_node *get_Block_graph_arr (ir_node *node, int pos);
inline void set_Block_graph_arr (ir_node *node, int pos, ir_node *value);
inline int get_End_n_keepalives(ir_node *end);
inline ir_node *get_End_keepalive(ir_node *end, int pos);
inline void add_End_keepalive (ir_node *end, ir_node *ka);
/* Some parts of the End node are allocated seperately -- their memory
is not recovered by dead_node_elimination if a End not is dead.
is not recovered by dead_node_elimination if a End node is dead.
free_End frees these data structures. */
inline void free_End (ir_node *end);
......@@ -480,7 +484,8 @@ inline int is_no_Block (ir_node *node);
Start, End, Jmp, Cond, Return, Raise, Bad */
int is_cfop(ir_node *node);
/* Returns true if the operation can change the control flow because