[M3devel] m3cc static chain stuff

Rodney M. Bates rodney_bates at lcwb.coop
Thu May 27 01:14:34 CEST 2010



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