2017-02-03 18 views
10

Запуск следующий код с clang++ -S -emit-llvm main.cpp && lli main.ll на Linux (Debian)ЛЛИ: LLVM ОШИБКА: Невозможно выбрать: X86ISD :: WrapperRIP TargetGlobalTLSAddress: i64

#include <future> 

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

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

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++ используют, что вызывает эту проблему?

EDIT:

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

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

Вот llvm-ir (это, к сожалению, большой, чтобы встроить его непосредственно здесь)

+1

Что вы подразумеваете под «компиляции и работает успешно» с libC++. Я получаю: LLVM ERROR: Программа использовала внешнюю функцию '_ZTVNSt3__114__shared_countE', которая не может быть решена! при запуске lli ... с помощью macOS? – Tobias

+0

да, вы правы, видимо, я использую пользовательскую сборку, которая содержит эти символы в двоичном формате; однако я в первую очередь заинтересован в понимании того, почему llvm orcjit не может запустить этот код * с * gcc стандартной библиотекой. – Gaetano

+1

https://llvm.org/bugs/show_bug.cgi?id=21431? Я знаю, что это mcjit, но, возможно, такая же проблема для orc – Tobias

ответ

3

EDIT:

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


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

lli выполняет только ИК-модуль и не связывает «неявное» соединение, как он должен знать, к каким библиотекам нужно подключаться?

Существуют различные решения этого, в зависимости от того, почему вы используете LLI:

  • компилировать и компоновать ИК-модуль: llc main.cpp && clang++ -lpthread main.s (нитей требуется s What is the correct link options to use std::thread in GCC under linux?.)
  • (неподтвержденные) использовать LD_PRELOAD="x.so y.so" для принудительно загружать библиотеки перед запуском lli
  • С программным обеспечением JIT модуль и используйте LoadLibraryPermanently(nullptr) (добавляет символы программы в пространство поиска) и LoadLibraryPermanently(file, err) для дополнительных библиотек (s. http://llvm.org/docs/doxygen/html/classllvm_1_1sys_1_1DynamicLibrary.html)

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

+0

Это не похоже на проблему с компоновщиком. Это побочная проблема: код даже не генерируется. – Joky

+0

@ Joky true, осознал, что только после того, как в ответ на вопрос. Это просто дополнительная проблема. Я отредактирую ответ. – Tobias

0

LLVM-DEV список рассылки отметил:

What does it mean?

LLVM-бэкенд в orcjit в настоящее время не поддерживает локальной памяти потока (TLS)

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

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

using -stdlib=libc++ compiles and runs successfully*; what specific features is libstdc++ using that cause this issue ?

это работает, потому что libC++ future :: получить реализацию не использует thread_local keywo радиолярии

Are there any compiler-flags that fix this problem?

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