[M3devel] m3cc static chain stuff

Tony Hosking hosking at cs.purdue.edu
Thu May 27 11:33:52 CEST 2010


The trampoline mechanism is broken on many platforms because they disable executable stacks.  I strongly favour retaining the current mechanisms.

On 26 May 2010, at 19:14, Rodney M. Bates wrote:

> 
> 
> Tony Hosking wrote:
>> We should endeavour to use the same functionality that the C compiler uses for its own nested functions, whereever possible.  The only thing is that we also build closures, so the trampoline mechanisms should be avoided.
> 
> I don't follow the last part of this argument.  If we follow the first
> principle, we would just use trampolines, since they are the same
> mechanism the C compiler uses.  And the only place they are not possible
> are places where they won't work for C either (e.g., a target where there
> is no place to construct code at runtime and have it be executable).
> The mere fact that we "also build closures" is not a necessity, just
> the reflection of the design decision to use the closure mechanism
> instead of trampolines.
> 
> OTHO, despite all the positive things I have said here and in another post
> about trampolines, I don't favor using them, because they would make m3gdb
> support a lot more difficult.  m3gdb needs to be able to both read and
> construct closures/trampolines, whichever.  Closures are almost target-
> independent, except for the native word size, which is already easily
> available to m3gdb.  Trampolines are going to be different for every
> instruction set, and the ones constructed by compiled code, at least,
> could even change with compiler version.  m3gdb would need a _lot_ of
> highly target-dependent code to handle them.
> 
>> Antony Hosking | Associate Professor | Computer Science | Purdue University
>> 305 N. University Street | West Lafayette | IN 47907 | USA
>> Office +1 765 494 6001 | Mobile +1 765 427 5484
>> On 26 May 2010, at 02:05, Jay K wrote:
>>> 
>>> Can any of this be removed?
>>> Can we really not just use "unfold-nested-procs" like NT386?
>>> We'd just lose a little bit of optimization, in rare cases, stop paying a bad cost/benefit ratio?
>>> Part of this is actually *deoptimization*. If the compiler decides the values aren't used, then it should
>>> be allowed to remove them. That is normal. Wanting to unused stuff in the debugger isn't
>>> generally a considered the responsibility of optimizers.
>>> 
>>> Therefore -- we could "unfold", remove our diffs, and gain some optimization and some deoptimization.
>>> Maybe I'll try without.
>>> 
>>> 
>>> diff -ur /src/orig/gcc-4.3.0/gcc/tree-nested.c /dev2/cm3/m3-sys/m3cc/gcc/gcc/tree-nested.c
>>> --- /src/orig/gcc-4.3.0/gcc/tree-nested.c    2008-02-15 09:36:43.000000000 -0800
>>> +++ /dev2/cm3/m3-sys/m3cc/gcc/gcc/tree-nested.c    2010-05-09 22:27:58.000000000 -0700
>>> 
>>> 
>>> -/* Build or return the RECORD_TYPE that describes the frame state that is
>>> -   shared between INFO->CONTEXT and its nested functions.  This record will
>>> -   not be complete until finalize_nesting_tree; up until that point we'll
>>> +/* This must agree with the string defined by the same name in m3gdb, file
>>> +   m3-util.c */
>>> +static const char * nonlocal_var_rec_name = "_nonlocal_var_rec";
>>> +
>>> +/* Build or return the RECORD_TYPE that describes the non-local frame struct
>>> +   that is shared between INFO->CONTEXT and its nested functions.  This record
>>> +   will not be complete until finalize_nesting_tree; up until that point we'll
>>>    be adding fields as necessary.
>>>     We also build the DECL that represents this frame in the function.  */
>>> @@ -209,7 +224,8 @@
>>>       free (name);
>>>        info->frame_type = type;
>>> -      info->frame_decl = create_tmp_var_for (info, type, "FRAME");
>>> +      info->frame_decl
>>> +        = create_tmp_var_for (info, type, nonlocal_var_rec_name);
>>>        /* ??? Always make it addressable for now, since it is meant to
>>>      be pointed to by the static chain pointer.  This pessimizes
>>> @@ -218,6 +234,8 @@
>>>      reachable, but the true pessimization is to create the non-
>>>      local frame structure in the first place.  */
>>>       TREE_ADDRESSABLE (info->frame_decl) = 1;
>>> +      /* m3gdb needs to know about this variable. */
>>> +      DECL_IGNORED_P (info->frame_decl) = 0;      }
>>>   return type;
>>> }
>>> @@ -290,6 +308,10 @@
>>>   return *slot;
>>> }
>>> +/* This must agree with the string defined by the same name in m3gdb, file
>>> +   m3_util.c */
>>> +static const char * static_link_var_name = "_static_link_var";
>>> +
>>> /* Build or return the variable that holds the static chain within
>>>    INFO->CONTEXT.  This variable may only be used within INFO->CONTEXT.  */
>>> @@ -310,9 +332,14 @@
>>>      Note also that it's represented as a parameter.  This is more
>>>      close to the truth, since the initial value does come from
>>>      the caller.  */
>>> -      decl = build_decl (PARM_DECL, create_tmp_var_name ("CHAIN"), type);
>>> +      decl = build_decl
>>> +               (PARM_DECL, get_identifier (static_link_var_name), type);
>>> +      TREE_CHAIN (decl) = NULL; /* Possibly redundant, but dbxout needs it. */
>>>       DECL_ARTIFICIAL (decl) = 1;
>>> -      DECL_IGNORED_P (decl) = 1;
>>> +
>>> +      /* m3gdb needs to know about this variable. */
>>> +      DECL_IGNORED_P (decl) = 0;
>>> +
>>>       TREE_USED (decl) = 1;
>>>       DECL_CONTEXT (decl) = info->context;
>>>       DECL_ARG_TYPE (decl) = type;
>>> @@ -326,7 +353,11 @@
>>>   return decl;
>>> }
>>> -/* Build or return the field within the non-local frame state that holds
>>> +/* This must agree with the string defined by the same name in m3gdb, file
>>> +   m3_util.c */
>>> +static const char * static_link_copy_field_name = "_static_link_copy_field";
>>> +
>>> +/* Build or return the field within the non-local frame struct that holds
>>>    the static chain for INFO->CONTEXT.  This is the way to walk back up
>>>    multiple nesting levels.  */
>>> @@ -339,10 +370,12 @@
>>>       tree type = build_pointer_type (get_frame_type (info->outer));
>>>        field = make_node (FIELD_DECL);
>>> -      DECL_NAME (field) = get_identifier ("__chain");
>>> +      DECL_NAME (field) = get_identifier (static_link_copy_field_name);
>>>       TREE_TYPE (field) = type;
>>>       DECL_ALIGN (field) = TYPE_ALIGN (type);
>>>       DECL_NONADDRESSABLE_P (field) = 1;
>>> +      /* m3gdb should know about this field. */
>>> +      DECL_IGNORED_P (field) = 0;         insert_field_into_struct (get_frame_type (info), field);
>>> @@ -465,7 +498,7 @@
>>>   return *slot;
>>> }
>>> -/* Build or return the field within the non-local frame state that holds
>>> +/* Build or return the field within the non-local frame struct that holds
>>>    the non-local goto "jmp_buf".  The buffer itself is maintained by the
>>>    rtl middle-end as dynamic stack space is allocated.  */
>>> @@ -1620,6 +1653,9 @@
>>>   switch (TREE_CODE (t))
>>>     {
>>>     case ADDR_EXPR:
>>> +      if (TREE_STATIC (t))
>>> +    break;
>>> +
>>>       /* Build
>>>        T.1 = &CHAIN->tramp;
>>>        T.2 = __builtin_adjust_trampoline (T.1);
>>> @@ -1714,6 +1750,22 @@
>>>     }
>>>       break;
>>> +    case STATIC_CHAIN_EXPR:
>>> +      decl = TREE_OPERAND (t, 0);
>>> +      target_context = decl_function_context (decl);
>>> +      if (target_context)
>>> +    {
>>> +      if (info->context == target_context)
>>> +        {
>>> +          /* Make sure frame_decl gets created.  */
>>> +          (void) get_frame_type (info);
>>> +        }
>>> +      *tp = get_static_chain (info, target_context, &wi->tsi);
>>> +    }
>>> +      else
>>> +    *tp = null_pointer_node;
>>> +      break;
>>> +
>>>     case RETURN_EXPR:
>>>     case GIMPLE_MODIFY_STMT:
>>>     case WITH_SIZE_EXPR:
>>> @@ -1768,13 +1820,22 @@
>>>   return NULL_TREE;
>>> }
>>> +static bool
>>> +debug_static_links (void)
>>> +{ return
>>> +    write_symbols != NO_DEBUG
>>> +    && debug_info_level != DINFO_LEVEL_NONE
>>> +    && debug_info_level != DINFO_LEVEL_TERSE;
>>> +
>>> +} /* debug_static_links */
>>> +
>>> /* Walk the nesting tree starting with ROOT, depth first.  Convert all
>>>    trampolines and call expressions.  On the way back up, determine if
>>>    a nested function actually uses its static chain; if not, remember that.  */
>>>  static void
>>> convert_all_function_calls (struct nesting_info *root)
>>> -{
>>> +{
>>>   do
>>>     {
>>>       if (root->inner)
>>> @@ -1784,7 +1845,10 @@
>>>       walk_function (convert_call_expr, root);
>>>        /* If the function does not use a static chain, then remember that.  */
>>> -      if (root->outer && !root->chain_decl && !root->chain_field)
>>> +      if (root->outer && !root->chain_decl && !root->chain_field
>>> +/* REMOVE ME: */
>>> +          /* && !debug_static_links () */
>>> +         )
>>>     DECL_NO_STATIC_CHAIN (root->context) = 1;
>>>       else
>>>     gcc_assert (!DECL_NO_STATIC_CHAIN (root->context));
>>> @@ -1806,6 +1870,21 @@
>>>   tree context = root->context;
>>>   struct function *sf;
>>> +/* REMOVEME: */
>>> +  /* If this is a nested function and we are supporting debugging via
>>> +     m3gdb, we always need a chain_decl, so m3gdb can find the static
>>> +     chain, even if the programmer's code doesn't use it. */
>>> +  if (false && root->outer && debug_static_links () )
>>> +    { tree static_chain_decl, temp, stmt;
>>> +      /* This is a desperate attempt to get later code generation to
>>> +         store the static link.  If it works, it'll be a miracle. */
>>> +      static_chain_decl = get_chain_decl (root);
>>> +      stmt = build_addr (static_chain_decl, root->context);
>>> +      temp = create_tmp_var_for (root, TREE_TYPE (static_chain_decl), NULL);
>>> +      stmt = build_gimple_modify_stmt (temp, static_chain_decl);
>>> +      append_to_statement_list (stmt, &stmt_list);
>>> +    }
>>> +
>>>   /* If we created a non-local frame type or decl, we need to lay them
>>>      out at this time.  */
>>>   if (root->frame_type)
>>> @@ -1912,7 +1991,7 @@
>>>      proper BIND_EXPR.  */
>>>   if (root->new_local_var_chain)
>>>     declare_vars (root->new_local_var_chain, DECL_SAVED_TREE (root->context),
>>> -          false);
>>> +          true);
>>>   if (root->debug_var_chain)
>>>     declare_vars (root->debug_var_chain, DECL_SAVED_TREE (root->context),
>>>           true);
>>> 
>>> 
>>>    




More information about the M3devel mailing list