[PATCH] D58160: Fix runtime problem from //bugs.llvm.org/show_bug.cgi?id=40323

Jennifer Yu via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 12 16:57:56 PST 2019


jyu2 created this revision.
jyu2 added reviewers: cfe-commits, rnk, majnemer, erichkeane.
Herald added subscribers: llvm-commits, jdoerfert.
Herald added a project: LLVM.

A MS only run time problem, because the init function for template static member is not getting called when the template static member is not reference.  To be able to evoke the init function, MS put the template static member in the linker directive section, that cause init function gets call.   As Rick suggest;  add template static data member to llvm.used that cause compiler to emit a similar -include directive into the linker directive section.

//bugs.llvm.org/show_bug.cgi?id=40323


Repository:
  rL LLVM

https://reviews.llvm.org/D58160

Files:
  lib/CodeGen/CGDeclCXX.cpp
  test/CodeGenCXX/microsoft-abi-template-static-init.cpp


Index: test/CodeGenCXX/microsoft-abi-template-static-init.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/microsoft-abi-template-static-init.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 %s -triple=i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-pc-windows-msvc -fms-extensions -emit-llvm -o - | FileCheck %s
+
+struct S {
+  S();
+  ~S();
+};
+
+template <typename T> struct __declspec(dllexport) ExportedTemplate {
+  static S s;
+};
+template <typename T> S ExportedTemplate<T>::s;
+void useExportedTemplate(ExportedTemplate<int> x) {
+  (void)x.s;
+}
+int f();
+namespace selectany_init {
+// MS don't put selectany static var in the linker directive, init routine
+// f() is not getting called if x is not referenced.
+int __declspec(selectany) x = f();
+}
+
+namespace explicit_template_instantiation {
+template <typename T> struct A { static  int x; };
+template <typename T> int A<T>::x = f();
+template struct A<int>;
+}
+
+namespace implicit_template_instantiation {
+template <typename T> struct A { static  int x; };
+template <typename T>  int A<T>::x = f();
+int g() { return A<int>::x; }
+}
+
+
+template <class T>
+struct X_ {
+  static T ioo;
+  static T init();
+};
+template <class T> T X_<T>::ioo = X_<T>::init();
+template struct X_<int>;
+
+template <class T>
+struct X {
+  static T ioo;
+  static T init();
+};
+// template specialized static data don't need in llvm.used,
+// the static init routine get call from _GLOBAL__sub_I_ routines.
+template <> int X<int>::ioo = X<int>::init();
+template struct X<int>;
+// CHECK: @llvm.global_ctors = appending global [6 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @"??__Ex at selectany_init@@YAXXZ", i8* bitcast (i32* @"?x at selectany_init@@3HA" to i8*) }, { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?x@?$A at H@explicit_template_instantiation@@2HA@@YAXXZ", i8* bitcast (i32* @"?x@?$A at H@explicit_template_instantiation@@2HA" to i8*) }, { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?ioo@?$X_ at H@@2HA@@YAXXZ", i8* bitcast (i32* @"?ioo@?$X_ at H@@2HA" to i8*) }, { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?s@?$ExportedTemplate at H@@2US@@A@@YAXXZ", i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate at H@@2US@@A", i32 0, i32 0) }, { i32, void ()*, i8* } { i32 65535, void ()* @"??__E?x@?$A at H@implicit_template_instantiation@@2HA@@YAXXZ", i8* bitcast (i32* @"?x@?$A at H@implicit_template_instantiation@@2HA" to i8*) }, { i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_microsoft_abi_template_static_init.cpp, i8* null }]
+// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast (i32* @"?x@?$A at H@explicit_template_instantiation@@2HA" to i8*), i8* bitcast (i32* @"?ioo@?$X_ at H@@2HA" to i8*), i8* getelementptr inbounds (%struct.S, %struct.S* @"?s@?$ExportedTemplate at H@@2US@@A", i32 0, i32 0), i8* bitcast (i32* @"?x@?$A at H@implicit_template_instantiation@@2HA" to i8*)], section "llvm.metadata"
+
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp
+++ lib/CodeGen/CGDeclCXX.cpp
@@ -481,6 +481,12 @@
     // minor startup time optimization.  In the MS C++ ABI, there are no guard
     // variables, so this COMDAT key is required for correctness.
     AddGlobalCtor(Fn, 65535, COMDATKey);
+    if (getTarget().getCXXABI().isMicrosoft()) {
+      // In The MS C++, MS add template static data member in the linker
+      // drective.
+      assert(COMDATKey);
+      addUsedGlobal(COMDATKey);
+    }
   } else if (D->hasAttr<SelectAnyAttr>()) {
     // SelectAny globals will be comdat-folded. Put the initializer into a
     // COMDAT group associated with the global, so the initializers get folded


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D58160.186563.patch
Type: text/x-patch
Size: 4014 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190213/2c7fe4d7/attachment.bin>


More information about the llvm-commits mailing list