clang: экспортировать символы неявно созданных функций с помощью O3 - PullRequest
0 голосов
/ 06 сентября 2018

TL, DR: Как заставить clang экспортировать символы неявно созданных функций, даже когда активен -O3?

Давайте возьмем следующий код:

#include <iostream>
#include <llvm/Support/DynamicLibrary.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>

template <typename T>
__attribute__((noinline))
int twice(const T& t) {
    return t * 2;
}

int thrice(const int& t) {
    return t * 3;
}

int main() {
    std::cout << twice(5) << std::endl;
    std::cout << thrice(5) << std::endl;

    llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);  // Make symbols from current process visible
    std::cout << "address of twice: " << llvm::RTDyldMemoryManager::getSymbolAddressInProcess("__Z5twiceIiEiRKT_") << std::endl;
    std::cout << "address of thrice: " << llvm::RTDyldMemoryManager::getSymbolAddressInProcess("__Z6thriceRKi") << std::endl;
}

Есть две функции, дважды и трижды. Первый шаблонизирован, второй нет. Сначала я регулярно звоню им, затем пытаюсь узнать их адрес с помощью libLLVM. Думайте об этом как о части супер упрощенного JIT-компилятора (у которого есть mangler, который приходит с именем).

При clang++ -O0 -I/usr/local/opt/llvm/include -L/usr/local/opt/llvm/lib/ jit.cpp -lLLVM (clang версия 6.0.0 на OS X) вывод будет таким, как ожидалось:

10
15
address of twice: 4350763184
address of thrice: 4350762224

Если я включу оптимизацию, символ для twice больше не будет экспортироваться, как видно из nm a.out | grep twice:

00000001000010b0 T __Z5twiceIiEiRKT_ (with -O0)
00000001000009c0 t __Z5twiceIiEiRKT_ (with -O3)

В результате libLLVM больше не находит функцию:

10
15
address of twice: 0
address of thrice: 4315621072

С помощью gcc символы экспортируются.

Я могу заставить clang экспортировать символ, если я его явно создаю:

template int twice<int>(const int& t);

Это, однако, на самом деле не вариант, так как мы не знаем, какие экземпляры будут вызываться механизмом JIT.

Мне известно о этом посте , но он имеет дело только с явными экземплярами.

1 Ответ

0 голосов
/ 07 сентября 2018

Добавить атрибут used, например:

template <typename T>
__attribute__((used))
int twice(const T& t) {
    return t * 2;
}

Это заставит Clang экспортировать символ.

...