[PATCH] D47354: [CodeGen][Darwin] Set the calling-convention of a thread-local variable initialization function to fix calling-convention mismatch

Akira Hatanaka via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu May 24 18:01:41 PDT 2018


ahatanak created this revision.
ahatanak added reviewers: rjmccall, t.p.northover.

There is a bug in IRGen where the calling convention of initialization functions for thread-local static members of c++ template classes isn't set. This caused InstCombine to remove a call to an initialization function because of the mismatch in the calling conventions between the initialization function and the call.

For example, when the following piece of code (this is in test/CodeGenCXX/cxx11-thread-local.cpp) is compiled,

  int g();
  template<typename T> struct V { static thread_local int m; };
  template<typename T> thread_local int V<T>::m = g();
  int e = V<int>::m;

IRGen generates the following IR:

  @_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__cxx_global_var_init.9
  
  define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() #2 {
    call cxx_fast_tlscc void @_ZTHN1VIiE1mE() ; this calls @__cxx_global_var_init.9
    ret i32* @_ZN1VIiE1mE
  }
  
  ; this function is missing the calling convention "cxx_fast_tlscc".
  
  define internal void @__cxx_global_var_init.9() #0 section "__TEXT,__StaticInit,regular,pure_instructions" {
    ...
  }

To fix the bug, this patch sets the calling convention of the initialization functions to 'cxx_fast_tlscc'. Alternatively, I could remove 'cxx_fast_tlscc' from the call instruction, but I suppose we don't want to do so for performance reasons.

rdar://problem/40447463


Repository:
  rC Clang

https://reviews.llvm.org/D47354

Files:
  lib/CodeGen/ItaniumCXXABI.cpp
  test/CodeGenCXX/cxx11-thread-local.cpp


Index: test/CodeGenCXX/cxx11-thread-local.cpp
===================================================================
--- test/CodeGenCXX/cxx11-thread-local.cpp
+++ test/CodeGenCXX/cxx11-thread-local.cpp
@@ -166,7 +166,8 @@
 // DARWIN: call cxx_fast_tlscc void @_ZTHN1XIiE1mE()
 // CHECK: ret {{.*}}* @_ZN1XIiE1mE
 
-// CHECK: define internal {{.*}} @[[VF_M_INIT]]()
+// LINUX: define internal void @[[VF_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[VF_M_INIT]]()
 // LINUX-SAME: comdat($_ZN1VIfE1mE)
 // DARWIN-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIfE1mE to i8*)
@@ -178,7 +179,8 @@
 // CHECK: store i64 1, i64* @_ZGVN1VIfE1mE
 // CHECK: br label
 
-// CHECK: define internal {{.*}} @[[XF_M_INIT]]()
+// LINUX: define internal void @[[XF_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[XF_M_INIT]]()
 // LINUX-SAME: comdat($_ZN1XIfE1mE)
 // DARWIN-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIfE1mE to i8*)
@@ -268,7 +270,8 @@
 // LINUX-LABEL: define internal i32* @_ZTWN12_GLOBAL__N_16anon_iE()
 // DARWIN-LABEL: define internal cxx_fast_tlscc i32* @_ZTWN12_GLOBAL__N_16anon_iE()
 
-// CHECK: define internal {{.*}} @[[V_M_INIT]]()
+// LINUX: define internal void @[[V_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[V_M_INIT]]()
 // LINUX-SAME: comdat($_ZN1VIiE1mE)
 // DARWIN-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*)
@@ -280,7 +283,8 @@
 // CHECK: store i64 1, i64* @_ZGVN1VIiE1mE
 // CHECK: br label
 
-// CHECK: define internal {{.*}} @[[X_M_INIT]]()
+// LINUX: define internal void @[[X_M_INIT]]()
+// DARWIN: define internal cxx_fast_tlscc void @[[X_M_INIT]]()
 // LINUX-SAME: comdat($_ZN1XIiE1mE)
 // DARWIN-NOT: comdat
 // CHECK: load i8, i8* bitcast (i64* @_ZGVN1XIiE1mE to i8*)
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -2450,8 +2450,12 @@
     if (InitIsInitFunc) {
       if (Init) {
         llvm::CallInst *CallVal = Builder.CreateCall(Init);
-        if (isThreadWrapperReplaceable(VD, CGM))
+        if (isThreadWrapperReplaceable(VD, CGM)) {
           CallVal->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+          llvm::Function *Fn =
+              cast<llvm::Function>(cast<llvm::GlobalAlias>(Init)->getAliasee());
+          Fn->setCallingConv(llvm::CallingConv::CXX_FAST_TLS);
+        }
       }
     } else {
       // Don't know whether we have an init function. Call it if it exists.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D47354.148531.patch
Type: text/x-patch
Size: 2561 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180525/b3360ba2/attachment.bin>


More information about the cfe-commits mailing list