Страницы

Поиск по вопросам

суббота, 4 января 2020 г.

Адрес функции на этапе компиляции

#cpp #cpp11


Задача: получить и преобразовать адрес функции. Смысл подразумевается следующий:

Имеем функцию 

void func() {}; // имеем адрес 0x500000, к примеру
constexpr size_t inc_pointer = to_size_t(&func) + 5; // (*)


Где to_size_t - это макрос/constexpr функция, которая преобразует адрес функции в
число на этапе компиляции. Реализация может быть следующая:

#define to_size_t(x) (size_t)(x) // C-style каст
#define to_size_t(x) reinterpret_cast(x) // C++-style каст


Почему я не написал cast сразу будет понятно ниже.

Проблема в том, что конструкция (*) превращается в следующий код

mov eax, 0x500000 // 0x500000 == адрес функции func
add eax, 5
...


Я же хочу добиться того, чтобы код был 

mov eax, 0x500005
...




Попытка 1

Сast'ы ни к чему хорошему не привели, результат выше



Попытка 2

template  union converter
{
    T _func;
    size_t _pointer;

    constexpr converter(T func) : _func(func) {};
};

#define to_size_t(x) converter{x}._pointer
#define identity(x) converter{x}._value


Для проверки constexpr'a я пользуюсь следующей функций:

template  void print_it() { std::cout << N << std::endl; }


Загвоздка в том, что constexpr union не хочет работать так, как мне нужно

print_it(); // ок, компилируется (обращение к полю _value)
print_it(); // error C2975: 'N': invalid template argument for 'print_it',
expected compile-time constant expression


Выслушаю ваши идеи.



P.S. А следующий код вообще крашит студию (2015-ю)

template  constexpr T identity_constexpr(T value) { return value; }

print>(); // fatal error C1001: An internal error has occurred
in the compiler.




UPDATE 

Ответ получен, видимо проблему придётся решать, заменяя конструкции соответствующим
образом уже после компиляции в готовом исполняемом файле. 
    


Ответы

Ответ 1



Всякий раз программа, вообще говоря, загружается в разное место в памяти - как тут можно говорить об адресе на уровне компиляции? Максимум, что можно (теоретически!) получить, и то на уровне компоновки - это относительное смещение адресов.

Ответ 2



Чисто предположения ради: попробовать распихать функции по разным секциям, а вот секциям задать адреса и размер через скрипт линковщика. Границы можно объявить экстерном и constexpr, тем самым обеспечив доступ к нужно информации на этапе компиляции. Может даже что-то выйти.

Комментариев нет:

Отправить комментарий