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

Reply via email to