Как эмулировать thread_local в llvm-ir?

Следующий код в настоящее время не работает в lli:

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

//clang++ -S -emit-llvm main.cpp && lli main.ll

LLVM-л:

; ModuleID = 'main.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"target triple = "x86_64-pc-linux-gnu"
@tls = external thread_local global i32, align 4

; Function Attrs: norecurse uwtable
define i32 @main() #0 {
%1 = alloca i32, align 4
store i32 0, i32* %1, align 4
%2 = call i32* @_ZTW3tls()
store i32 42, i32* %2, align 4
ret i32 0
}

define weak_odr hidden i32* @_ZTW3tls() {
br i1 icmp ne (void ()* @_ZTH3tls, void ()* null), label %1, label %2

; <label>:1                                       ; preds = %0
call void @_ZTH3tls()
br label %2

; <label>:2                                       ; preds = %1, %0
ret i32* @tls
}

declare extern_weak void @_ZTH3tls()

Это вызывает следующую ошибку:

LLVM ERROR: Cannot select: 0x55ec0e9c3a60: i64 = X86ISD::WrapperRIP
TargetGlobalTLSAddress:i64<i32* @tls> 0 [TF=10]
0x55ec0e9c3858: i64 = TargetGlobalTLSAddress<i32* @tls> 0 [TF=10]
In function: _ZTW3tls

Есть ли способ эмулировать TLS и преобразовать llvm-ir, чтобы заставить это работать?

Можно ли использовать глобальную карту от thread_id до указателей и заменять каждое вхождение локального потока на allocator / deallocator / getter / setter?

Являются -femulated-tls а также -ftls-model какого-либо использования?

связанные вопросы:

Как выполнить TargetLowering в проходе ИК-трансформации?

http://lists.llvm.org/pipermail/llvm-dev/2017-February/109947.html

25

Решение

Так как вы не сказали, в чем ошибка, которую вы видите, я предполагаю, что это что-то вроде
LLVM ERROR: Program used external function '_ZTH3tls' which could not be resolved!

Это ошибка связывания, которая на самом деле относится к тому факту, что tls объявляется как имеющее внешнюю связь, но нет другого определения для ссылки (по крайней мере, вы опубликовали).

замещать

extern thread_local int tls;

с

thread_local int tls;

Затем компилятор сгенерирует следующий IR

@tls = thread_local global i32 0, align 4

Если вам действительно нужно иметь внешнюю связь и использовать lliвам нужно будет связать файлы llvm с llvm-link впервые с lli не имеет возможности ссылаться на себя.

например

ext.cpp

thread_local int tls = 0;

main.cpp

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

Компиляция этого сгенерирует ext.ll а также main.ll, Бежать llvm-link -S ext.ll main.ll > output.ll чтобы получить связанный файл, а затем lli output.ll также должен работать.

Дайте мне знать, если это все решит.

1

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

Других решений пока нет …

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