Как добавить встроенную функцию в плагин 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() тогда, но вы можете сохранить DECL, возвращенный 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 но как вызов обычной функции. Я действительно нуждался в встроенной функции, чтобы избежать вызова, а вместо этого вставить тело функции.

С другой стороны, tsan0 pass, который выполняется сразу после моего pass, вставляет вызовы встроенных функций, как и следовало ожидать: в результате явного вызова нет, просто вставляется тело функции. Однако его встроенные функции определяются самим GCC, а не подключаемыми модулями.

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

0 ответов

Я предполагаю, что вы хотите (из вашего комментария и связанного сообщения) вставить код C в функцию. В этом случае я бы подумал, что вам не нужно заходить так далеко, чтобы писать плагин компилятора. Взгляните на Boost.Preprocessor, который может выполнять очень сложные манипуляции с кодом C, используя только препроцессор.

Другие вопросы по тегам