[comp.lang.ada] how do I do pointers to functions i

stt@inmet.inmet.com (12/04/89)

To call a subprogram, given only its address...

With some Ada compilers, it is possible to provide
an address clause for a pragma-interfaced subprogram
with a non-static address.  This means that the following
might work:

    procedure Real_Proc(B : Integer) is
    begin ... end Real_Proc;

. . .

    Proc_Addr : System.Address;

. . .

    Proc_Addr := Real_Proc'ADDRESS;

. . .

    procedure Dummy_Proc(B : Integer);
    pragma Interface(Ada, Dummy_Proc);
    for Dummy_Proc use at Proc_Addr;

. . .

    Dummy_Proc(42);

However, we have found that with most compilers we need to drop into
assembler to call a procedure given only its address.
This usually only requires a couple of lines of assembler.
For example:

    procedure Call_Ada_Proc(
      Param : Integer;
      Proc : System.Address
    );
    pragma Interface(Assembler, Call_Ada_Proc);

    . . .

    Call_Ada_Proc(42, Proc_Addr);

Depending on parameter passing conventions,
the code for Call_Ada_Proc can sometimes be a single
instruction which passes control to the address passed
as the last parameter.  By putting the address parameter
last, the earlier parameters are often already in the
"right" place (e.g. register or stack offset).

Since the address-clause "trick" is compiler-dependent
anyway, dropping into assembler is not a bad
alternative.  This is one of those
things we can hope will be solved as part of the Ada9X
process, since it seems like a common problem.
Of course, no guarantees...

S. Tucker Taft
Intermetrics, Inc.
Cambridge, MA  02138

edm@vrdxhq.verdix.com (Ed Matthews) (12/06/89)

In article <20600024@inmet> stt@inmet.inmet.com writes:
>
>However, we have found that with most compilers we need to drop into
>assembler to call a procedure given only its address.
>This usually only requires a couple of lines of assembler.
>For example:
>
>    procedure Call_Ada_Proc(
>      Param : Integer;
>      Proc : System.Address
>    );
>    pragma Interface(Assembler, Call_Ada_Proc);

The Verdix VADS compiler is an exception to the above.  You can use a
machine code insertion to do the same thing.  We use this trick when
passing function pointers to C code.

with Machine_Code;
with System;
procedure Call(
    Function_Ptr : in System.Address;
    Param        : in Integer_32) is

    procedure Do_Call(Param : in Integer_32) is
        use Machine_Code;
    begin
        -------------------------------------------
        -- Stack is set up correctly so just do  --
        -- a branch to the start of the function --
        -------------------------------------------
        Code_1'(JMP, Function_Ptr'Ref);
	---------------------------------------------------------
	-- JMP is an enumeration literal of type OP_CODE from  --
	-- package Machine_Code.  The 'Ref attribute generates --
	-- a reference to an Ada object.                       --
	---------------------------------------------------------
    end Do_Call;

begin
    Do_Call(Param);
end Call;
-- 

Ed Matthews                                                edm@verdix.com
Verdix Corporation Headquarters                            (703) 378-7600
Chantilly, Virginia