lli: LLVM ОШИБКА: невозможно выбрать: X86ISD :: WrapperRIP TargetGlobalTLSАдрес: i64

Выполнение следующего кода с clang++ -S -emit-llvm main.cpp && lli main.ll в Linux (Debian)

#include <future>

int main () {
return std::async([]{return 1;}).get();
}

не запускается на lli из-за следующей ошибки:

LLVM ERROR: Cannot select: 0xd012e0:
i64 = X86ISD::WrapperRIP TargetGlobalTLSAddress:i64<i8** @_ZSt15__once_callable> 0 [TF=10]

0xd020c0: i64 = TargetGlobalTLSAddress<i8** @_ZSt15__once_callable> 0 [TF=10]
In function: _ZSt9call_onceIMNSt13__future_base13_State_baseV2EFvPSt8functionIFSt10unique_ptrINS0_12_Result_baseENS4_8_DeleterEEvEEPbEJPS1_S9_SA_EEvRSt9once_flagOT_DpOT0_

Вопросы:

Что это значит?

Существуют ли какие-либо флаги компилятора, которые решают эту проблему?

с помощью -stdlib=libc++ компилируется и запускается успешно *; какие особенности libstdc ++ использует, которые вызывают эту проблему?

РЕДАКТИРОВАТЬ:

Мотивация этого вопроса состоит в том, чтобы понять различия между libc ++ и libstdc ++, которые приводят к этому конкретному сообщению об ошибке (в Linux) в orvjit llvm.

В OSX gcc устарел и clang использует по умолчанию libc++,
Чтобы воспроизвести эту ошибку на OSX, вам, вероятно, нужно установить gcc & использование -stdlib=libstdc++,

Здесь LLVM-л (к большому сожалению, вставлять его сюда напрямую)

10

Решение

РЕДАКТИРОВАТЬ:

Ошибка оказалась вызвана отсутствием поддержки TLS в JITer. Этот ответ описывает другую проблему, связанную со связыванием и lli,


Если вы посмотрите на сгенерированный IR от clang++ -std=c++11 -S -emit-llvm test.cppвы найдете, что многие из символов, например, _ZNSt6futureIiE3getEv, только объявлены, но никогда не определены. Линкер никогда не вызывается, так как -S «Выполнять только шаги предварительной обработки и компиляции» (clang —help).

lli выполняет только модуль IR и не выполняет «неявного» связывания. Как он должен знать, в какие библиотеки связывать?

Есть разные решения для этого, в зависимости от того, почему вы используете lli:

Я могу только догадываться, почему libc ++ работает для вас, поскольку он не работает на моей машине, но, вероятно, это так, потому что он уже загружен в lli и вызывает lli sys::DynamicLibrary::LoadLibraryPermanently(nullptr) добавить символы программы в пространство поиска JIT (s. https://github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110).

3

Другие решения

Список рассылки LLVM-dev указал:

Что это значит?

База данных llvm в orcjit в настоящее время не поддерживает локальное хранилище потоков (TLS)

минимальный пример:

extern thread_local int tls;
int main() {
tls = 42;
return 0;
}

использование -stdlib = libc ++ компилируется и успешно выполняется *; какие особенности libstdc ++ использует, которые вызывают эту проблему?

это работает, потому что libc ++ future :: get реализация не использует thread_local ключевое слово.

Существуют ли какие-либо флаги компилятора, которые решают эту проблему?

В настоящее время нет решения.
С помощью lli -relocation-model=pic обменивает эту проблему с ошибкой перемещения.

1

По вопросам рекламы [email protected]