c++ - ¿Cómo emular thread_local en llvm-ir?
multithreading lli (1)
El siguiente código actualmente no funciona en lli:
//main.cpp
extern thread_local int tls;
int main() {
tls = 42;
return 0;
}
//clang++ -S -emit-llvm main.cpp && lli main.ll
llvm-ir:
; 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()
Causa el siguiente error:
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
¿Hay una manera de emular TLS y transformar el llvm-ir para hacer que esto funcione?
¿Sería factible utilizar un mapa global desde thread_id a punteros y reemplazar cada ocurrencia de subprocesos locales con asignador / desasignador / captador / configurador?
¿Son -femulated-tls
y -ftls-model
de cualquier uso?
preguntas relacionadas:
¿Cómo realizar TargetLowering en un pase de transformación IR?
http://lists.llvm.org/pipermail/llvm-dev/2017-February/109947.html
Ya que no ha dicho cuál es el error que está viendo, supongo que es algo de la forma LLVM ERROR: Program used external function ''_ZTH3tls'' which could not be resolved!
Este es un error de vinculación, que en realidad se refiere al hecho de que tls
está declarado como que tiene una vinculación externa, pero no hay otra definición a la que vincular (al menos que hayas publicado).
Reemplazar
extern thread_local int tls;
con
thread_local int tls;
El compilador generará el siguiente IR
@tls = thread_local global i32 0, align 4
Si realmente necesita tener un enlace externo y usar lli
, primero deberá vincular los archivos llvm-link
con llvm-link
ya que lli
no tiene la capacidad de vincularse por sí mismo.
p.ej
ext.cpp
thread_local int tls = 0;
main.cpp
extern thread_local int tls;
int main() {
tls = 42;
return 0;
}
Compilar esto generará ext.ll
y main.ll
Ejecute llvm-link -S ext.ll main.ll > output.ll
para obtener el archivo vinculado y luego lli output.ll
también debería funcionar.
Déjame saber si eso lo resuelve.