Now approach to instrument pointer calls. The instrumenter inserts _POINTER_CALL(call) around such calls. Then the tracer ignores _FUNC(num) except that we had a _POINTER_CALL().
Example:
foo( x );
void (*fun)(int) = foo;
fun( x );
mystruct->myfun( x );
metafun( y ) ( x );
fun( random() );
Instrumented: with instrumenter.py FILENAME --pointer-calls
foo( x );
void (*fun)(int) = foo;
_POINTER_CALL(fun( x ));
_POINTER_CALL(mystruct->myfun( x ));
_POINTER_CALL_AFTER(metafun( y )) ( x );
fun( _POINTER_CALL_AFTER(random()) );
Note: To make use of it when tracing/retracing, compile with -D_TRACE_POINTER_CALLS_ONLY! Then we trace only function numbers for pointer calls. Otherwise the macros will be without effect and every function number gets traced.
Technical details: The clang.cindex, well, does not exactly expose pointer calls. But it is possible to indirectly detect "normal" function calls, by checking if they reference a CursorKind.FUNCTION_DECL. Otherwise, it would reference for example a CursorKind.VAR_DECL or to a member in a struct. Or if you use pointer-arithmetic, there could be no reference at all.
When in trace mode, _POINTER_CALL(...) sets a global variable _trace_pointer_call to true. _FUNC(num) is only active when this variable is true. After _FUNC(num) is done, _trace_pointer_call is set to false again. Since the pointer and function arguments are evaluated before the call, we use the _POINTER_CALL_AFTER(other_call) in these situtations instead, to set _trace_pointer_call only after the other call finished.
Solves #36.
Now approach to instrument pointer calls. The instrumenter inserts
_POINTER_CALL(call)
around such calls. Then the tracer ignores_FUNC(num)
except that we had a_POINTER_CALL()
.Example:
Instrumented: with
instrumenter.py FILENAME --pointer-calls
Note: To make use of it when tracing/retracing, compile with
-D_TRACE_POINTER_CALLS_ONLY
! Then we trace only function numbers for pointer calls. Otherwise the macros will be without effect and every function number gets traced.Technical details: The clang.cindex, well, does not exactly expose pointer calls. But it is possible to indirectly detect "normal" function calls, by checking if they reference a
CursorKind.FUNCTION_DECL
. Otherwise, it would reference for example aCursorKind.VAR_DECL
or to a member in a struct. Or if you use pointer-arithmetic, there could be no reference at all.When in trace mode,
_POINTER_CALL(...)
sets a global variable_trace_pointer_call
to true._FUNC(num)
is only active when this variable is true. After_FUNC(num)
is done,_trace_pointer_call
is set to false again. Since the pointer and function arguments are evaluated before the call, we use the_POINTER_CALL_AFTER(other_call)
in these situtations instead, to set_trace_pointer_call
only after the other call finished.