Howto "goto address_x;"

F

Frank

Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
....
address_x = MyLabel;
....
goto address_x;


I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum', such as

enum { Label1, Label2, Label3, ... } address_x;

GotoStartPoint:
switch( address_x ) {
case Label1: ...
case Label2: ...
case Label3: ...
}
....
address_x = Label2;
goto GotoStartPoint;

But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

Is there any way to get arround that?

Best Regards

Frank
 
M

Mark McIntyre

Frank said:
It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

(snip somewhat confusing code).

What are you /actually/ trying to achieve ? The snipped code looks like
an attempt to solve some problem or other which you haven't explained.
 
U

user923005

Before I start,  please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
...
     address_x = MyLabel;
...
     goto address_x;

I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum', such as

enum { Label1, Label2, Label3, ... } address_x;

GotoStartPoint:
switch( address_x ) {
case Label1: ...
case Label2: ...
case Label3: ...}

...
address_x = Label2;
goto GotoStartPoint;

But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

Is there any way to get arround that?

Before writing coroutines, ask yourself, "Is it really worth it?"
After all, someone is going to have to maintain it.

Anyway, this will show you what you are after:
http://www.google.com/search?hl=en&q=coroutines
 
R

Ravishankar S

Frank said:
Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
...
address_x = MyLabel;
...
goto address_x;


I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum', such as

enum { Label1, Label2, Label3, ... } address_x;

GotoStartPoint:
switch( address_x ) {
case Label1: ...
case Label2: ...
case Label3: ...
}
...
address_x = Label2;
goto GotoStartPoint;

But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

Is there any way to get arround that?

Best Regards

Frank

GNU C has the extension of label variables and allows you to jump to any
such evaluated address.

Labels as Values
================

You can get the address of a label defined in the current function
(or a containing function) with the unary operator `&&'. The value has
type `void *'. This value is a constant and can be used wherever a
constant of that type is valid. For example:

void *ptr;
/* ... */
ptr = &&foo;

To use these values, you need to be able to jump to one. This is
done with the computed goto statement(1), `goto *EXP;'. For example,

goto *ptr;

Any expression of type `void *' is allowed.

One way of using these constants is in initializing a static array
that will serve as a jump table:

static void *array[] = { &&foo, &&bar, &&hack };

Then you can select a label with indexing, like this:

goto *array;
 
R

Ravishankar S

Ravishankar S said:
GNU C has the extension of label variables and allows you to jump to any
such evaluated address.

I forgot the disclaimer :) : Its completely non-standard !
Labels as Values
================

You can get the address of a label defined in the current function
(or a containing function) with the unary operator `&&'. The value has
type `void *'. This value is a constant and can be used wherever a
constant of that type is valid. For example:

void *ptr;
/* ... */
ptr = &&foo;

To use these values, you need to be able to jump to one. This is
done with the computed goto statement(1), `goto *EXP;'. For example,

goto *ptr;

Any expression of type `void *' is allowed.

One way of using these constants is in initializing a static array
that will serve as a jump table:

static void *array[] = { &&foo, &&bar, &&hack };

Then you can select a label with indexing, like this:

goto *array;
 
M

Mark Bluemel

Frank said:
Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

It would also be interesting to know what you are really trying to
achieve. We might be better able to suggest a solution which doesn't
abuse the language.

[snip]
I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum',
[snip]


But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

So you don't just want a trick, you want to apply some measure to it to
determine if it's "efficient" enough for you?

Perhaps I won't give my solution based on an array of jmpbufs and
longjmp(), then...
Is there any way to get arround that?

Use a different language?

Consider using subroutine calls rather than branches? The language
supports function pointers, but not label pointers (apart from
non-standard extensions such as that used by GCC).
 
M

Mark F. Haigh

Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
...
address_x = MyLabel;
...
goto address_x;

I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum', such as

enum { Label1, Label2, Label3, ... } address_x;

GotoStartPoint:
switch( address_x ) {
case Label1: ...
case Label2: ...
case Label3: ...}

...
address_x = Label2;
goto GotoStartPoint;

But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

Is there any way to get arround that?
<snip>

Perhaps you're looking for something like this:

#include <stdio.h>
#include <stdlib.h>

typedef void (*func_t)(void);
typedef func_t (*next_t)(void);

func_t foo(void);
func_t bar(void);

func_t foo(void)
{
printf("foo()\n");
return (func_t) bar;
}

func_t bar(void)
{
printf("bar()\n");
return (func_t) foo;
}

int main(void)
{
next_t f = foo;
while(1)
f = (next_t) f();

/* Never reached */
return 0;
}

Note that func_t is used as a generic function pointer type. In an
ideal world, you could use void *, but that wouldn't be strictly
conforming due to reasons I won't go into.

Typically you'll get fairly tight assembly out of this kind of thing,
but always do timing measurements on your platforms of interest. It's
really the only way to be sure, and sometimes the results are quite
surprising.

Mark F. Haigh
(e-mail address removed)
 
C

Chris Hills

Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
...
address_x = MyLabel;
...
goto address_x;

Yes it is quite easy BUT in the compilers where it is easy it is
completely compiler specific.

AFAIK there is no standard why of doing this elegantly
 
R

Richard Heathfield

Frank said:
Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable

Make the variable a function pointer, and assign it the address of a
function. Then just call the function through the pointer. It's more of a
gosub than a goto, but you'll end up with a better design, so that's all
to the good.
 
R

Richard Tobin

Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

It would be interesting to know a trick how to get C to do a goto to
an address that has been assigned to a variable, i.e.

MyLabel:
...
address_x = MyLabel;
...
goto address_x;


I tried to pack the positions into a switch statement and made
'address_x' a variable of type 'enum', such as

enum { Label1, Label2, Label3, ... } address_x;

GotoStartPoint:
switch( address_x ) {
case Label1: ...
case Label2: ...
case Label3: ...
}
...
address_x = Label2;
goto GotoStartPoint;

But when I look at the assembler code, it is not as efficient as a
jump to an address assigned to a variable.

Is there any way to get arround that?

We used to edit the assembler code :)

I assume you have ensured (by profiling) that this really is the
bottle-neck in your code.

Some compilers (notably gcc) have an extension allowing you to assign
labels to variables. Depending on your portability constraints, this
may well be the best solution.

You could use function addresses instead of course, but presumably you
would be concerned about the call overhead, and access to shared
variables.

You maybe able to make the switch more efficient by using an unsigned
char variable and providing code for all 256[*] cases, so that the
switch code doesn't have to do range checking.

[*] Why yes, I *am* assuming 8-bit bytes.

-- Richard
 
B

Bart C

Mark said:
It would also be interesting to know what you are really trying to
achieve. We might be better able to suggest a solution which doesn't
abuse the language.

Use a different language?

It's possible the OP is doing just that as he mentioned generated code. In
that case it doesn't matter so much that the result may be inelegant
and might difficult to maintain.

I was looking at something similar myself: given labels A,B,C,D,... to
arbitrarily jump say to label B then D then A then perhaps B again according
to a table of input data, without the overheads of a function call and
ideally without even the overhead of loop control.

Apparently one answer then is to use GCC.

Bart
 
S

Spiro Trikaliotis

Hello,

Mark McIntyre said:
What are you /actually/ trying to achieve ? The snipped code looks like
an attempt to solve some problem or other which you haven't explained.

Perhaps, he wants to write something like "protothreads"
(http://www.sics.se/~adam/pt/about.html)? Unfortunately, that
implementation also uses either a switch(), or the GCC extension, if
availble, to implement this.

Regards,
Spiro.
 
T

Tor Rustad

Frank said:
Before I start, please let's not discuss whether goto is evil or not.
For generated code, this can make perfect sense.

In such cases, what is the problem with


void foo(void)
{
L1: stmt1;
L2: stmt2;
L3: stmt3;
L4: stmt4;
L5: stmt5;
L6: stmt6;

goto ...;

}

???

When generating code, I see no need for label "address". So, you need to
explain why this is relevant.
 
T

Tor Rustad

Ravishankar said:
GNU C has the extension of label variables and allows you to jump to any
such evaluated address.

So? OP could even generate this code:

....

static char jmp[7] =
"\xbd\x00\x00\x00\x00" /* movl $0,%ebp */
"\xff\xe5"; /* jmp *%ebp */


....

memcpy( jmp_table[NR], jmp, 7);

....

((int (*)) jmp_table[NR])();
 
R

Richard Tobin

GNU C has the extension of label variables and allows you to jump to any
such evaluated address.
[/QUOTE]
So? OP could even generate this code:
[machine code deleted]

That would be a far less portable solution.

-- Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top