Replies: 1 comment
-
@IGI-111 : As promised. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Consider a variable in the source language that gets initialized to a function pointer:
The question is how to perform the dispatch to the function that
f
points to when only relative jumps are available in the assembly target.To do this we need two things for every function type
T
in the program (there are a finite number of such types, and they are known statically):T
. (There are a finite number of function of that type, and those functions are known statically).i
and a set of arguments, looks up itemi
in the function pointer array, and calls that function with the set of arguments (the typechecker guarantees that the types of the arguments match the function being called).In pseudo-code the dispatch function looks something like this:
fn dispatch_X_Y_Z_W (index: int, x: X, y: Y, z: Z) -> W {
let fps = <constant pool array for type (X, Y, Z) -> W>;
fps[index](x, y, z) // This is the call point for
fun1
orfun2
}
In the example above we would get something like the following:
(X, Y, Z) -> W
, and two functions of that typefun1
andfun2
.fun1
andfun2
will be located at addressesaddr_fun1
andaddr_fun2
, respectively.(X, Y, Z) -> W
contains a single call point for the functions of type(X, Y, Z) -> W
. That callpoint is located at addressaddr_callpoint_X_Y_Z_W
.[ addr_fun1 - addr_callpoint_X_Y_Z_W, addr_fun2 - addr_callpoint_X_Y_Z_W ]
. These are the addresses of the functions of types(X, Y, Z) -> W
relative to the single call point for those functions.in the example above the line
let f = if ... { fun1 } else { fun2 }
would evaluate to a struct containingthen
branch or theelse
branch gets taken. Whichever function pointer the expression evaluates to we know statically which index in the constant pool entry each potential result corresponds to.Once the function pointer gets applied in the line
let x = f (a, b, c)
, this performs a call to the dispatch function:f
.index
is the index from the struct value off
.Since the address of the dispatch function is known statically, we can always statically determine the relative address from any call site to the dispatch function. And since the addresses of the functions of the relevant type are known statically, and now only have a single call site (inside the dispatch function), the relative addresses of the calls to those functions are also known statically.
The end result is that function pointers can be implemented using relative addresses.
Beta Was this translation helpful? Give feedback.
All reactions