It is possible for a GCC plugin to add a new builtin function? If so, how to do it properly?
GCC version is 5.3 (or newer). The code being compiled and processed by the plugin is written in C.
It is mentioned in the rationale for GCC plugins at gcc-melt.org that this is doable but I cannot see how.
As far as I can see in the sources of GCC, the builtins are created using add_builtin_function()
from gcc/langhooks.c:
tree
add_builtin_function (const char *name,
tree type,
int function_code,
enum built_in_class cl,
const char *library_name,
tree attrs)
It is more or less clear which values the arguments of this function should have, except for function_code
, a unique numeric ID of the function.
Looks like (see add_builtin_function_common()
), a value from enum built_in_function
is expected there but a GCC plugin cannot change that enum.
One cannot pass any random value greater than END_BUILTINS
as function_code
either, it seems. builtin_decl_implicit()
and builtin_decl_explicit()
would have a failed assertion in that case.
So, what is the proper way to add a builtin in a GCC plugin (without using MELT and such, just GCC plugin API)?
Update
I looked again at the implementation of add_builtin_function_common()
and of langhooks.builtin_function()
for C as well as at how these are used in GCC. It seems that 0 is acceptable as function_code
in some cases. You cannot use builtin_decl_implicit()
then but you can save the DECL returned by add_builtin_function()
and use it later.
Looks like the only event when I can try to create builtins that way is PLUGIN_START_UNIT (otherwise GCC may crash due to external_scope
variable being NULL).
I tried the following at that stage (fntype
was created before):
decl = add_builtin_function (
"my_helper", fntype,
0 /* function_code */,
BUILT_IN_NORMAL /* enum built_in_class cl */,
NULL /* library_name */,
NULL_TREE /* attrs */)
my_helper
was defined in a different C source file compiled and linked with the main source file. Then I used decl to insert the calls to that function into other functions (gimple_build_call
) during my GIMPLE pass.
GCC output no errors and indeed inserted the call to my_helper
but as a call to an ordinary function. I actually needed a builtin to avoid a call but rather insert the body of the function.
On the other hand, tsan0
pass, which executes right after my pass, inserts the calls of builtin functions just like one would expect: there is no explicit call as a result, just the body of the function is inserted. Its builtins, however, are defined by GCC itself rather than by the plugins.
So I suppose my builtin still needs something to be a valid builtin, but I do not know what it is. What could that be?