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 & use -stdlib=libstdc++,

Вот что такое llvm-ir (к сожалению, встраивать его здесь напрямую)

2 ответа

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

Ошибка оказалась вызвана отсутствием поддержки 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 (см. https://github.com/llvm-mirror/llvm/blob/release_40/tools/lli/OrcLazyJIT.cpp#L110).

Список рассылки 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 обменивает эту проблему с ошибкой перемещения.

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