goto *(function pointer)

Akif Ozkan
2013-03-07
2013-03-15
  • Akif Ozkan

    Akif Ozkan - 2013-03-07

    Is goto *(function pointer) is supported in SDCC.
    As I see it is not. Also SDCC isn't compile this code.

    But is there any other way to do this without using asm?

    ( I want to implement a function which will go directly to another function after finishing its job.
    And go to the main function from the second one.
    Second function would be generic. So all I can change is the first function. )

     
  • Maarten Brock

    Maarten Brock - 2013-03-07

    A function pointer call is no goto. That aside, SDCC does support function pointers. Which target are you using and what is 'this code' you try to compile?

     
  • Akif Ozkan

    Akif Ozkan - 2013-03-08

    Thanks for replying,

    I am using SDCC for 8051.
    Yes, I can use function pointers.

    I want to jump another address at the end of a function.
    As I see,
            goto label is supported.
    but  goto *pointer is not.

    Is there a way to do this in C code?

     
  • Maarten Brock

    Maarten Brock - 2013-03-09

    C does not support goto *pointer. It would also violate all rules for structured programming. If you would jump to another function the calling function would not be properly ended and cleaned up resulting in stack overflow.

    You should just call the function pointer and let it return to the end of the calling function. And if you use -peep-return and you have the luck that there is nothing to clean up then SDCC will change the CALL + RET into a JUMP.

     
  • David Cary

    David Cary - 2013-03-10

    My understanding is that:
    You have a variable that contains pointer to some pre-written leaf function that you don't want to change.
    You want to write a new function.
    You want that new function to in some cases (a) start executing that leaf function, and then (b) when that leaf function is finished, it does not continue with the "other stuff" your function does, but immediately returns to the function that called the function you are writing.
    In other cases, you want that new function function to skip (a) and (b), and instead do other stuff.

    The standard way to do that in C code is something like

    typedef  void (*MyFunctionReturningVoid)( int );
    typedef  int (*MyFunctionReturningInt)( int );

    // warning, untested code
    void my_void_function( MyFunctionReturningVoid pfv, int x ){
        // … do some preliminary stuff
        if( 0 != x ){
            // early exit when x is not zero.
            (*pfv)(x);
            return;
            // the peephole optimizer converts the *2* above lines to "JUMP pfv", not the "CALL pfv; RETURN" you might expect.
        };
        // do other stuff, but only when x was zero.
        printf(" apparently x was zero. ");
        return;
    }

    // warning, untested code
    int my_int_function( MyFunctionReturningInt pfi, int x ){
        // … do some preliminary stuff
        if( 0 != x ){
            // early exit when x is not zero.
            int return_val = (*pfi)(x);
            return return_val;
            // the peephole optimizer converts the *2* above lines to "JUMP pfi", not the "CALL pfi; RETURN" you might expect.
        };
        // do other stuff, but only when x was zero.
        printf(" apparently x was zero. ");
        return 7;
    }

    For more information about using function pointers in C,
    refer to any standard C programming manual, such as
    http://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays#Pointers_to_Functions

    As far as I know, the only SDCC-specific thing you need to worry about here is:
    Whenever you call a function through a function pointer, that function must be declared reentrant with the "__reentrant" keyword (unless that function has 2 bytes or less of parameters), whenever you're compiling for the 8051 or any other target that is not automatically reentrant by default.

     
  • Akif Ozkan

    Akif Ozkan - 2013-03-13

    If I understood you (David) correctly you just described how function pointers work.

    My problem wasn't like that and Maarten understood correctly.

    I am working on a critical application and I trace PC.

    So if condition in the func1 occurs program should jump to func2, otherwise program should go back to main.
    Once program flow is decided PC should never come back to func1.

    In gcc you can use goto *pointer.
    But this is also unstable and costructed for labels again.
    (You get label address using &&label1)

    So I asked if there is anyway to do this in C.

    As Maarten said sometimes SDCC makes -peep-return optimization, but as I see this is very limited.

    So I got the job done in ASM.
    Here is the code:


    void func1( unsigned char sent, void (*pt2func)(unsigned char));
    void func2(unsigned char input);

    int main( void )
    {
    func1( 1,,func2);

    return ( 0 );
    

    }

    void func2(unsigned char input)
    {
    ...
    }

    void func1( unsigned char sent,void (*pt2func)(unsigned char),unsigned char )
    {
    ...

    if (sent==1){
    //pt2func(4);
    __asm
            push    _func1_PARM_2
        push    (_func1_PARM_2 + 1)
        mov dpl,#0x04
        ;ret
    __endasm;
    }
    __asm
    ret
    __endasm;
    

    }

    I simply change the return address of func1, if condition occurs.

    But a designer should care about the following code of the func1 exit.
    Ending of func1 should be thought as naked.

    Do you see any mistake in here?

     
  • Maarten Brock

    Maarten Brock - 2013-03-15

    When you start messing with the stack in such a manner, I advise to write the whole func1 function in ASM. You can use __naked to suppress the prologue and epilogue code. And you should be aware that the calling convention depends on memory model and stack options.

    But I don't really see why you're so determined to get rid of this one RET at the cost of such unmaintainable code.

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks