On Sun, Mar 20, 2005 at 02:58:29AM +0100, Giovanni Bajo wrote:

> It is possible in GNU C at least:
> 
> int foo(int dest)
> {
>    __label__ l1, l2, l3;
>    void *lb[] = { &&l1, &&l2, &&l3 };
>    int x = 0;
> 
>    goto *lb[dest];
> 
> l1:
>    x += 1;
> l2:
>    x += 1;
> l3:
>    x += 1;
>    return x;
> }

Thanks for explaining this.  So yes, unfortunately we have to support
indirect_jump properly (I was hoping it was only for something like
trampolines, which can't work on the AVR anyway).

I was wrong about needing two jumps - just one for each label should
be enough, because switching to .text_low and back to .text doesn't
disrupt the normal flow of instructions in .text.  So, it's not that
bad, really the same thing for indirect jumps and calls (using function
pointers), each affected label needs to be output like this:

        .section .text_low,"ax",@progbits
label:
        jmp 1f
        .text
1:

This includes all global labels (visible to other object files, like
function entry points), and local labels referenced by anything other
than direct jumps or calls).

On the other hand, branches within the same function should avoid the
extra jump and go to "1:" directly.  If the same label is used in both
ways (direct jump/branch, and address taken), two separate labels (at
the same address) should be output for both of these uses, but I'm not
sure how to do this in GCC.  Any suggestions?

(The problem can be seen by adding something like "if (dest > 2) goto l3;"
above the goto in the original example: in the assembler output, there is
only one label corresponding to l3 which is both 1. referenced with pm()
and 2. target of a branch for which .text_low would be out of range.)

Marek

Reply via email to