Design and Methodology

Currently, our tree structures are way too large. For a VAR_DECL node on a 32 bit machine, 108 bytes are needed. On a 64 bit machine, 208 bytes are needed. The majority of the shared fields and flags are not set or used on a VAR_DECL. Thus far, the goal of choosing what trees to split and how to split them has been mainly one of size reduction, and thus, trees have been split where it is easy to do so, and it will reduce the size. More interesting reducions, such as removing the need for shared fields, or any other type of restructuring, have not been done.

The following methodology was used to discover how to split up the codes into structures as a rough estimate:

Choosing how to split

Choose a given tree code to be split out of the currently common nodes.

  1. Discover what fields really need to be used in that tree
    1. For each field that is shared through >1 macro, if one macro is guarded with a non-specific class check (like DECL_CHECK), *and* one macro is guarded by a code specific check (like VAR_DECL_CHECK) for your tree code:

      1. Instrument the non-specific check with a check that aborts if given your tree code.
      2. Attempt to bootstrap and regtest the compiler to see if anybody accesses this field using your tree code with the other macro.
      3. If the places that need to be changed to get the compiler to not abort are not easily changeable, this field probably needs to be in a base class shared among the codes that use it
    2. For each field that is shared through >1 macro, if the macro is guarded with a non-specific class check (like DECL_CHECK) *and* no macro is guarded by a code specific check (like VAR_DECL_CHECK) for your tree code:

      1. Instrument the non-specific check with a check that aborts if given your tree code.
      2. If the places that need to be changed to get the compiler to not abort are not easily changeable, this field probably needs to be in a base class shared among the codesthat use it
    3. Any fields with two or more specific checks (IE TREE_CODE_CHECK2 (NODE, VAR_DECL, PARM_DECL) need to either be in a base class for both nodes, or in the common decl node.

    4. Look at front-ends to see how they use the field, in their *.h and *.c files, in the same way as above. Any usage in new tree codes could be split into a new structure inherited from the structure with the field they are trying to access.

  1. For fields that need to be in some base class because they are used by >1 tree code, see if they commonly share some feature that would make sense giving them their own base class.

  2. See if the field is used in a way that it makes sense to split out of tree_decl_common (IE used by 4 out of 6 tree codes) to warrant it's own base class.

<b> No fields shall be accessed by front ends without dynamic type checking, at least at the start so that corner cases of field use can be caught</b> This gives a rough structure like so (only shared fields are in parantheses):

struct tree_decl_minimal (common, locus, uid, context, name)
|
-> struct tree_decl_common (align, size, mode, size_unit, attributes)
  |
  -> struct tree_field_decl  -- FIELD_DECL
  |
  -> struct tree_label_decl -- LABEL_DECL
  |
  -> struct tree_type_decl -- TYPE_DECL
  |
  -> struct tree_translation_unit_decl -- TRANSLATION_UNIT_DECL
  |
  -> struct tree_decl_with_rtl (rtl)
    |
    -> struct tree_result_decl -- RESULT_DECL
    |
    -> struct tree_const_decl -- CONST_DECL
    |
    -> struct tree parm_decl -- PARM_DECL
    |
    -> struct tree_decl_with_vis (section_name, assembler name, visibility)
      |
      -> struct tree_var_decl -- VAR_DECL
      |
      -> struct tree_function_decl -- FUNCTION_DECL

Splitting

Each may have further inherited structures in the front ends.

Handling dynamic checking

There are a variety of approaches to handling dynamic checking in the face of inheritance by front ends.

  1. don't do dynamic checking at all
  2. only do it on the common portions we know are not inherited by anything in the frontend.
  3. Use casting and magic.
  4. Note structure containment info in some way that takes the inheritance into account.

Approach 3 is the approach i plan on taking, with the current alternate implementations are planned:

  1. A doubly indexed array is created, called unsigned char tree_contains_structure[N_TREE_CODES][N_TREE_STRUCTURE_ENUMS] This array will currently be 255 * 12 max, and if we have one tree structure for every tree code, it would be 255 * 255 max.

  2. tree_contains_structure[code][enumname] is 1 if the tree for code contains the structure for enum embedded in it. This is set up by both the common init, and FE inits, to contain the right set of 1's and 0's

  3. Checking macros are updated to make sure the structure they are attempting to access is contained in the tree code.

alternately,

  1. A mask of tree structure enums is noted using [gccsource:tree.def] and embedded directly in the tree when checking is on.
  2. Checking macros are updated to check the mask for the correct enum before performing the access

Inheriting a tree structure in a frontend

Currently, our frontends define their own tree structures, but only inherit through lang_specific pointers and overloading existing fields.

Instead, language specific inheritance will be provided directly, and all inherited structures will be visible in the union tree_node and enum tree_node_structure Inherited structure may derive from any of the provided tree structures, and must set up the approriate dynamic checking table in the frontend initialization.

However, language specific macros to use these fields will only be accessible from the approriate frontends, to prevent leakage into the language independent portions.

The inheritance will be included into the tree union by creating a header file of the extra structures and enums at configure time, based on what languages are to be enabled.

Thus, union tree_node will look like this:

union  tree_node_d
{
  struct foo GTY ((tag ("TS_FOO_TREE")));
  struct bar GTY ((tag ("TS_BAR_TREE")));
  <other common tree structures>
#include "lang_tree_structs.h"
}

and enum tree_node_structure will look like this:

enum tree_node_structure
{
   TS_FOO_TREE,
   TS_BAR_TREE,
   <other common tree enums>
  #include "lang_ts_enums.h"
}

None: New_DECL_hierarchy (last edited 2008-01-10 19:38:55 by localhost)