What do you think of the following plan for turning cgraph into
a class hierarchy? We cannot finish it until we have gengtype
understanding single inheritance, but we can start changing APIs
in preparation.
EXISTING ###########################################
enum symtab_type { SYMTAB_SYMBOL, SYMTAB_FUNCTION, SYMTAB_VARIABLE };
struct symtab_node_base /* marked SYMTAB_SYMBOL */
embeds symtab_type
struct cgraph_node /* marked SYMTAB_FUNCTION */
embeds leading struct symtab_node_base symbol;
struct cgraph_local_info local;
struct cgraph_global_info global;
struct cgraph_rtl_info rtl;
struct cgraph_clone_info clone;
struct cgraph_thunk_info thunk;
typedef struct cgraph_node *cgraph_node_ptr;
struct varpool_node /* marked SYMTAB_VARIABLE */
embeds leading struct symtab_node_base symbol;
cgraph.h:typedef struct varpool_node *varpool_node_ptr;
union symtab_node_def
struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
typedef union symtab_node_def *symtab_node;
typedef const union symtab_node_def *const_symtab_node;
static inline struct cgraph_node *cgraph (symtab_node node);
static inline struct varpool_node *varpool (symtab_node node);
APPROACH ###########################################
Add converters and testers.
Change callers to use those.
Change callers to use type-safe parameters.
Change implementation to class hierarchy.
Add accessors.
CONVERTERS AND TESTERS ###########################################
add
symtab_node_base &symtab_node_def::ref_symbol()
{ return symbol; }
symtab_node_base &cgraph_node::ref_symbol()
{ return symbol; }
symtab_node_base &varpool_node::ref_symbol()
{ return symbol; }
change
node->symbol.whatever
to
node->ref_symbol().whatever
----
should not need to add these
cgraph_node &symtab_node_def::ref_cgraph()
{ gcc_assert (symbol.type == SYMTAB_FUNCTION);
return x_function; }
varpool_node &symtab_node_def::ref_varpool()
{ gcc_assert (symbol.type == SYMTAB_VARIABLE);
return x_variable; }
----
add
symtab_node_base *symtab_node_def::try_symbol()
{ return &symbol; }
cgraph_node *symtab_node_def::try_cgraph()
{ return symbol.type == SYMTAB_FUNCTION ? &x_function : NULL; }
varpool_node *symtab_node_def::try_varpool()
{ return symbol.type == SYMTAB_VARIABLE ? &x_variable : NULL; }
change
if (symtab_function_p (node) && cgraph (node)->analyzed)
return cgraph (node);
to
if (cgraph_node *p = node->try_cgraph())
if (p->analyzed)
return p;
change
if (symtab_function_p (node) && cgraph (node)->callers)
....
to
if (cgraph_node *p = node->try_cgraph())
if (p->callers)
....
change
if (symtab_function_p (node))
{
struct cgraph_node *cnode = cgraph (node);
....
to
if (cgraph_node *cnode = node->try_cgraph ())
{
....
likewise "symtab_variable_p (node)" and "varpool (node)"
----
If there are any "symtab_function_p (node)" expressions left,
add
bool symtab_node_def::is_cgraph()
{ return symbol.type == SYMTAB_FUNCTION; }
bool symtab_node_def::is_varpool()
{ return symbol.type == SYMTAB_VARIABLE; }
change
symtab_function_p (node)
to
node->is_cgraph ()
likewise "symtab_variable_p (node)"
----
Though we would like to avoid doing so,
if there are any "cgraph (node)" or "varpool (node)" expressions left,
add
symtab_node_base *symtab_node_def::ptr_symbol()
{ return &symbol; }
cgraph_node *symtab_node_def::ptr_cgraph()
{ gcc_assert (symbol.type == SYMTAB_FUNCTION);
{ return &x_function; }
varpool_node *symtab_node_def::ptr_varpool()
{ gcc_assert (symbol.type == SYMTAB_VARIABLE);
{ return &x_variable; }
change
cgraph (node) => node->ptr_cgraph()
likewise "varpool (node)"
TYPE SAFETY ###########################################
If a function asserts that its symtab_node parameter is symtab_function_p,
then convert the function to take a cgraph_node*
and change the callers to convert as above.
PROPOSED HIERARCHY ###########################################
enum symtab_type { SYMTAB_SYMBOL, SYMTAB_FUNCTION, SYMTAB_VARIABLE };
struct symtab_node_base /* marked SYMTAB_SYMBOL */
embeds symtab_type
cgraph_node : symtab_node_base /* marked SYMTAB_FUNCTION */
varpool_node : symtab_node_base /* marked SYMTAB_VARIABLE */
changing
typedef union symtab_node_def *symtab_node;
typedef const union symtab_node_def *const_symtab_node;
to
typedef symtab_node_base *symtab_node;
typedef const symtab_node_base *const_symtab_node;
changing used of
symtab_node_def
to
symtab_node_base
--
Lawrence Crowl