Для целей оптимизации очень низкого уровня мне было бы полезно, если бы я мог хранить скомпилированную функцию непосредственно в переменной, не указатель на функцию. То есть, если у меня есть функция foo, я хочу сделать буфер символов достаточно большим, чтобы в нем могли храниться машинные инструкции, сгенерированные для foo, и затем иметь возможность фактически вызывать foo, каким-то образом указав C, чтобы перейти к выполнению содержимого этого буфера. (предположим, что у меня есть встроенный компилятор, чтобы убедиться, что буфер символов правильно выровнен для моей архитектуры). В идеале я хотел бы сделать это, сводя использование сборки к минимуму (я понимаю, что некоторые из них могут потребоваться).
Моим лучшим решением до сих пор было бы скомпилировать программу, имеющую только функцию, которую я хочу собрать с GCC, затем скомпилировать в машинный код, а затем использовать адреса из выведенной сборки, чтобы извлечь желаемый машинный код из исполняемого файла, затем вручную заполните буфер этим в моей программе, затем используйте встроенную сборку, чтобы перейти к начальному адресу буфера. Это более хакерская и ручная работа, чем мне бы хотелось.
Мне не нужно компилировать новые функции во время выполнения, просто в буфере содержатся инструкции, соответствующие различным уже скомпилированным функциям во время выполнения. Например. Я мог бы иметь 3 скомпилированные функции и 1 буфер. Эти 3 функции известны во время компиляции, но во время выполнения буфер может соответствовать любому из 3 в разное время.
Редактировать: Чтобы уточнить, что можно получить: у меня есть структура, членом которой будет этот буфер, и различные указатели на экземпляры этой структуры. Каждый буфер структуры может содержать различную скомпилированную функцию. Если бы я использовал указатель на функцию вместо буфера, мне пришлось бы загрузить указатель на функцию struct, а затем разыменовать указатель на функцию. С помощью буфера я могу просто переместить программный счетчик к смещению (относительному расположению буфера) основания структуры. Это на один уровень косвенности меньше. Для очень маленьких функций это может быть экономией.
Редактировать 2: дальнейшее уточнение:
С указателем на функцию:
- Загрузить указатель из & struct + offsetof (pointer)
- Перейти к местоположению, содержащемуся в указателе
С буфером, содержащим машинный код:
- Перейти к & struct + offsetof (buffer)
Второй шаг меньше.