[M3devel] m3cc static chain stuff
Tony Hosking
hosking at cs.purdue.edu
Thu May 27 11:32:19 CEST 2010
On 26 May 2010, at 18:56, Jay K wrote:
>
>>> Nested functions should be transformed to not be nested. Imho.
>
>> I don't understand this. Nested functions must be nested in the sense that
>> they have static chain information provided by gcc.
>
>
>
> Can it be achieved by adding an extra parameter instead?
The compiler *does* (inside gcc) add an extra parameter.
>
>
>>> Optimization should be allowed to inhibit debugging as much as it does for any other language.
>> What do you mean by this?
>
>
>
> It looks like we inhibit optimization if -g is specified.
> Like we preserve unused static chains.
> This is has been discussed and I have to look at the code more..
> Generating debug information should not inhibit optimisation.
Generating debug information inhibits optimisations where sufficient state needs to be kept around to support symbolic debugging. I don't think it inhibits optimisation in any way we care about.
>
>
>
> - Jay
>
>
>
> ----------------------------------------
>> From: hosking at cs.purdue.edu
>> Date: Wed, 26 May 2010 10:26:32 -0400
>> To: jay.krell at cornell.edu
>> CC: m3devel at elegosoft.com
>> Subject: Re: [M3devel] m3cc static chain stuff
>>
>> On 26 May 2010, at 03:55, Jay K wrote:
>>
>>>
>>> I'm going to try to keep the code that seems to do anything, however:
>>>
>>> 1) if (false &&
>>>
>>> I plan to remove that.
>>>
>>>
>>> 2)
>>> + if (root->outer && !root->chain_decl && !root->chain_field
>>> +/* REMOVE ME: */
>>> + /* && !debug_static_links () */
>>> + )
>>>
>>>
>>> I can't find where that would apply, and it is commented out anyway so I'll remove it.
>>>
>>>
>>> I'm open to arguments though. :)
>>>
>>> dbxout.c
>>> +#if 0
>>> +/* Code copied from 1.4.2.2: */
>>>
>>>
>>> I can cheaply enough keep that...should we really though?
>>>
>>>
>>> I really think we can reduce our changes.
>>> Enough type information should be passed around so that regular gdb works. Imho.
>>
>> Possibly, but M3 has a very different notion of type to C. Moreover, it is extremely valuable to have the M3 type ids there so that functionality can map back to the types in the M3 runtime system. It would be possible to implement much of the m3gdb debugging support by calling back into the language run-time passing the language type ids instead of relying on hand-crafted C in m3gdb. But I agree that more type information would be good, particularly for records.
>>
>>> And so that we can use Dwarf or regular -g -- ie. so various -g options other than -gstabs
>>> don't cause internal compiler errors. So that debug info might be generated on systems
>>> that don't support stabs though granted they are few and minor (hppa64-hpux).
>>> Nested functions should be transformed to not be nested. Imho.
>>
>> I don't understand this. Nested functions must be nested in the sense that they have static chain information provided by gcc.
>>
>>> Optimization should be allowed to inhibit debugging as much as it does for any other language.
>>
>> What do you mean by this?
>>
>>>
>>>
>>> I realize the type information getting around is probably a lot of work.
>>> And it is needed in m3back also, and probably not shared work.
>>>
>>>
>>> - Jay
>>>
>>> ----------------------------------------
>>>> From: jay.krell at cornell.edu
>>>> To: m3devel at elegosoft.com
>>>> Subject: m3cc static chain stuff
>>>> Date: Wed, 26 May 2010 06:05:25 +0000
>>>>
>>>>
>>>> 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);
>>>>
>>>>
>>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20100527/eb4fff1e/attachment-0002.html>
More information about the M3devel
mailing list