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 is compiled and processed by the plugin 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 built-ins 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?
GCC provides built-in versions of the ISO C99 floating-point comparison macros that avoid raising exceptions for unordered operands. They have the same names as the standard macros ( isgreater , isgreaterequal , isless , islessequal , islessgreater , and isunordered ) , with __builtin_ prefixed.
GCC plugins are loadable modules that provide extra features to the compiler. Like GCC itself they can be distributed in source and binary forms. GCC plugins provide developers with a rich subset of the GCC API to allow them to extend GCC as they see fit.
I'm assuming what you want to do (from your comment and linked post) is insert C code into a function. In that case, I would have thought you wouldn't need to go so far as to write a compiler plugin. Have a look at Boost.Preprocessor, which can do very advanced manipulations of C code using only the preprocessor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With