Как добавить встроенную функцию в плагин 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, а не подключаемыми модулями.

Так что я полагаю, что моей встроенной функции все еще нужно что-то, чтобы быть действительной встроенной функцией, но я не знаю, что это такое. Что бы это могло быть?

Ответы