Как добавить встроенную функцию в плагин GCC?
Возможно ли для плагина GCC добавить новую встроенную функцию? Если так, как это сделать правильно?
Версия GCC 5.3 (или новее). Код, который компилируется и обрабатывается плагином, написан на C.
В обосновании плагинов GCC на gcc-melt.org упоминается, что это выполнимо, но я не вижу, как это сделать.
Насколько я вижу в источниках GCC, встроенные функции создаются с использованием add_builtin_function()
из 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)
Более или менее ясно, какие значения должны иметь аргументы этой функции, за исключением function_code
, уникального числового идентификатора функции.
Похоже (смотрите add_builtin_function_common()
), там ожидается значение из enum built_in_function
, но плагин GCC не может изменить это перечисление.
Никто не может передать любое случайное значение, большее, чем END_BUILTINS
как function_code
либо, кажется. builtin_decl_implicit()
и builtin_decl_explicit()
будет иметь ошибочное утверждение в этом случае.
Итак, как правильно добавить встроенный модуль в плагин GCC (без использования MELT и т.д., Только API плагинов GCC)?
Обновление Я снова посмотрел на реализацию add_builtin_function_common()
и langhooks.builtin_function()
для C, а также на то, как они используются в GCC. Похоже, что 0 приемлем в качестве function_code
в некоторых случаях. Вы не можете использовать builtin_decl_implicit()
тогда, но вы можете сохранить add_builtin_function()
возвращенный add_builtin_function()
и использовать его позже.
Похоже, единственное событие, когда я могу попытаться создать встроенные функции таким образом, это PLUGIN_START_UNIT (в противном случае GCC может завершиться сбоем из-за того, что переменная external_scope
равна NULL).
На этом этапе я попробовал следующее (fntype
был создан ранее):
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
был определен в другом исходном файле C, скомпилированном и связанном с основным исходным файлом. Затем я использовал decl для вставки вызовов этой функции в другие функции (gimple_build_call
) во время моего прохода GIMPLE.
GCC не my_helper
ошибок и действительно вставляет вызов my_helper
но как вызов обычной функции. Я действительно нуждался в встроенной функции, чтобы избежать вызова, а вместо этого вставить тело функции.
С другой стороны, tsan0
pass, который выполняется сразу после моего pass, вставляет вызовы встроенных функций, как и следовало ожидать: в результате явного вызова нет, просто вставляется тело функции. Однако его встроенные функции определяются самим GCC, а не подключаемыми модулями.
Так что я полагаю, что моей встроенной функции все еще нужно что-то, чтобы быть действительной встроенной функцией, но я не знаю, что это такое. Что бы это могло быть?