public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "timo.kreuzer at reactos dot org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug middle-end/37722] destructors not called on computed goto
Date: Fri, 11 Jan 2013 14:52:00 -0000	[thread overview]
Message-ID: <bug-37722-4-5XHQ1YfT9p@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-37722-4@http.gcc.gnu.org/bugzilla/>


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37722

Timo Kreuzer <timo.kreuzer at reactos dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timo.kreuzer at reactos dot
                   |                            |org

--- Comment #3 from Timo Kreuzer <timo.kreuzer at reactos dot org> 2013-01-11 14:52:03 UTC ---
(In reply to comment #2)
> int bar(int idx) {
>     static void* const gotos[] = {&&RETRY, &&INSIDE, &&OUTSIDE, &&EVIL};
>     bool first = true;
>     {
>     RETRY:
>         foo<1> f1;
>         if(first) {
>             first = false;

Well usually you cannot declare a variable after a label. That's a gcc
extension. So you should either add curly braces between RETRY and INSIDE, or
move RETRY above the preceeding brace. But that is just syntax, since it would
be desired that it behaved like it would with a normal goto, even if that was
placed like that. (I assume normal gotos will handle this properly)

To theoretically solve the proplem, you could replace every indirect goto with
code like this:

{
    static void* const local_gotos[] = {&&label1, &&label2, &&label3,
&&label4};
    goto *local_gotos[idx];
label1: goto RETRY;
label2: goto INSIDE;
label3: goto OUTSIDE;
label4: goto EVIL;
}

And now have the compiler optimize the pathes.
This way, there are no more crazy jumps, just a very simple indirect jump and a
number of normal jumps that the compiler should be able to handle anyway.

The problem is now, that there might be multiple indirect jumps that use the
same static data, which is just a bunch of void pointers.
So depending on the origin of the jump different pathes would need to be
generated for each target. This is incompatible with an indirect jump
instruction though, which only utilizes some arbitrary address.

One possible solution for this is to always invoke all destructors and
constructors, even for local indirect gotos. So you would need to consider an
indirect jump to always leave all scope blocks, up to the top level of the
function and reenter from there. This would allow to generate labels/codepathes
that are consistent for multiple indirect gotos.

Another solution, is to use multiple jump tables. One table for each indirect
goto containing one entry for each possibly referenced label in the function.
The trick is that the original label addresses, that are produced with the &&
operator will all point to an "array" of direct jmp instructions. all of the
same size. Now the first indirect goto would emit an indirect jump instruction
to the address itself. The second one would substract the address of the first
label, divide by the size of the jmp stub code and use the result as an index
into it's own private jump table. Alternatively a static offset could be added
to the actual address and multiple direct jump stubs would be generated in a
row.

table:
  .long label1, label2, label3, label4;

table2:
  .long label1_from_2, label2_from_2, label3_from_2, label4_from_2;

   // first indirect goto
   mov eax, table[ecx * 4] // get the address from the table
   jmp eax // jump there

   // Second indirect goto
   mov ecx, table[ecx * 4] // get the address from the table
   sub ecx, label1 // substract the address of the first label
   shr ecx, 3 // divide by 8 (assuming each stub is 8 bytes)
   mov eax, table[ecx * 4] // get the address from the 2nd table
   jmp eax // jump there

   // Alternative: using multiple stub arrays
   mov eax, table[ecx * 4] // get the address from the table
   add eax, label5 - label1 // add the offset to the second "jmp array"
   jmp eax // jump there

label1: jmp label1_from_1
label2: jmp label2_from_1
label3: jmp label3_from_1
label4: jmp label4_from_1

label5: jmp label1_from_2
label6: jmp label2_from_2
label7: jmp label3_from_2
label8: jmp label4_from_2

This mechanism would only be needed as soon as multiple indirect jumps could
reference the same labels and different code pathes would need to be
constructed for the targets depending on the origin of the goto.
As an optimization it should be considered that labels, of which the address
has been put in a table, which is now out of scope are not actually available
anymore. Other optimizations might be using 2 different tables directly, if
they are only used for 2 indirect jumps (someone might (mis)use it for
different things like non-local gotos, exception handling, saving the address
of code that is being executed for debugging purposes, etc)


       reply	other threads:[~2013-01-11 14:52 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <bug-37722-4@http.gcc.gnu.org/bugzilla/>
2013-01-11 14:52 ` timo.kreuzer at reactos dot org [this message]
2022-01-03 12:00 ` pinskia at gcc dot gnu.org
2022-01-03 17:33 ` jakub at gcc dot gnu.org
2023-07-19 16:46 ` ndesaulniers at google dot com
2023-12-21  2:07 ` cvs-commit at gcc dot gnu.org
2023-12-21  2:08 ` jason at gcc dot gnu.org
2024-01-03  4:23 ` egallager at gcc dot gnu.org
2008-10-02 20:46 [Bug c++/37722] New: " cburger at sunysb dot edu
2008-10-02 21:23 ` [Bug middle-end/37722] " pinskia at gcc dot gnu dot org
2009-05-09  8:17 ` scovich at gmail dot com

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-37722-4-5XHQ1YfT9p@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).