compnerd updated this revision to Diff 104028.
compnerd added a comment.

Handle unnamed parameters, improve mangling for NSDMis.  The one case that we 
dont handle currently causes an assertion even in itanium mode.


https://reviews.llvm.org/D34523

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCXX/msabi-blocks.cpp

Index: test/CodeGenCXX/msabi-blocks.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/msabi-blocks.cpp
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X86
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -std=c++11 -fblocks -S -o - -emit-llvm %s | FileCheck %s -check-prefix CHECK-X64
+
+extern int e(void);
+
+void (^b)() = ^{
+  static int i = 0;
+};
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke@@YAXPAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke@@YAXPEAU__block_literal@@@Z@4HA" ={{.*}} global i32 0
+
+void f(void) {
+  static int i = 0;
+  ^{ static int i = e(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+  ^{ static int i = e(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_2@@YAXPAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_2@@YAXPEAU__block_literal_2@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+
+  ^{ ^{ static int i = e(); }(); }();
+
+// CHECK-X86-DAG: @"\01?i@?1??_block_invoke_3@@YAXPAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?1??_block_invoke_3@@YAXPEAU__block_literal_3@@@Z?1??_block_invoke_4@@YAXPEAU__block_literal_4@@@Z?1??f@@YAXXZ@4HA" ={{.*}} global i32 0
+}
+
+
+template <typename>
+void g(void) {
+  ^{ static int i = e(); }();
+}
+
+template void g<char>(void);
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@D@@YAXXZ@4HA" ={{.*}} global i32 0
+
+template void g<int>(void);
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2???$g@H@@YAXXZ@4HA" ={{.*}} global i32 0
+
+inline void h(void) {
+  ^{ static int i = e(); }();
+}
+
+// CHECK-X86-DAG: @"\01?i@?2??_block_invoke_1@@YAXPAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?2??_block_invoke_1@@YAXPEAU__block_literal_1@@@Z?2??h@@YAXXZ@4HA" ={{.*}} global i32 0
+
+struct s {
+  int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+  int j = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@j@s@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+  void m(int i = ^{ static int i = e(); return ++i; }(),
+         int j = ^{ static int i = e(); return ++i; }()) {}
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??m@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??m@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+
+  void n(int = ^{ static int i = e(); return ++i; }(),
+         int = ^{ static int i = e(); return ++i; }()) {}
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPAU__block_literal_1_1@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPAU__block_literal_1_2@@@Z?0??n@s@@QAEXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_1@@YAXPEAU__block_literal_1_1@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1_2@@YAXPEAU__block_literal_1_2@@@Z?0??n@s@@QEAAXHH@Z@4HA" ={{.*}} global i32 0
+
+};
+
+struct t {
+  struct u {
+    int i = ^{ static int i = e(); return ++i; }();
+
+// CHECK-X86-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+// CHECK-X64-DAG: @"\01?i@?0??_block_invoke_1@0u@t@@YAXPEAU__block_literal_1@@@Z@4HA" ={{.*}} global i32 0
+
+  };
+};
+
+void j(void) {
+  h();
+  struct s s;
+  s.m();
+  s.n();
+  struct t::u t;
+}
+
+#if 0
+template <typename T>
+struct v {
+  static T i;
+};
+
+template <typename T>
+T v<T>::i = ^{ static T i = T(); return i; }();
+
+template class v<char>;
+template class v<int>;
+#endif
+
Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -966,16 +966,71 @@
     }
 
     if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
-      DiagnosticsEngine &Diags = Context.getDiags();
-      unsigned DiagID =
-          Diags.getCustomDiagID(DiagnosticsEngine::Error,
-                                "cannot mangle a local inside this block yet");
-      Diags.Report(BD->getLocation(), DiagID);
-
-      // FIXME: This is completely, utterly, wrong; see ItaniumMangle
-      // for how this should be done.
-      Out << "__block_invoke" << Context.getBlockId(BD, false);
-      Out << '@';
+      auto Discriminate =
+          [](StringRef Name, const unsigned Discriminator,
+             const unsigned ParameterDiscriminator) -> std::string {
+        std::string Buffer;
+        llvm::raw_string_ostream Stream(Buffer);
+        Stream << Name;
+        if (Discriminator)
+          Stream << '_' << Discriminator;
+        if (ParameterDiscriminator)
+          Stream << '_' << ParameterDiscriminator;
+        return Stream.str();
+      };
+
+      unsigned Discriminator = BD->getBlockManglingNumber();
+      if (!Discriminator)
+        Discriminator = Context.getBlockId(BD, /*Local=*/false);
+
+      // Mangle the parameter position as a discriminator to deal with unnamed
+      // parameters.  Rather than mangling the unqualified parameter name,
+      // always use the position to give a uniform mangling.
+      unsigned ParameterDiscriminator = 0;
+      if (const auto *MC = BD->getBlockManglingContextDecl())
+        if (const auto *P = dyn_cast<ParmVarDecl>(MC))
+          if (const auto *F = dyn_cast<FunctionDecl>(P->getDeclContext()))
+            ParameterDiscriminator =
+                F->getNumParams() - P->getFunctionScopeIndex();
+
+      DC = getEffectiveDeclContext(BD);
+
+      Out << '?';
+      mangleSourceName(Discriminate("_block_invoke", Discriminator,
+                                    ParameterDiscriminator));
+      // If we have a block mangling context, encode that now.  This allows us
+      // to discriminate between named static data initializers in the same
+      // scope.  This is handled differently from parameters, which use
+      // positions to discriminate between multiple instances.
+      if (const auto *MC = BD->getBlockManglingContextDecl())
+        if (!isa<ParmVarDecl>(MC))
+          if (const auto *ND = dyn_cast<NamedDecl>(MC))
+            mangleUnqualifiedName(ND);
+      // MS ABI and Itanium manglings are in inverted scopes.  In the case of a
+      // RecordDecl, mangle the entire scope hierachy at this point rather than
+      // just the unqualified name to get the ordering correct.
+      if (const auto *RD = dyn_cast<RecordDecl>(DC))
+        mangleName(RD);
+      else
+        Out << '@';
+      // void __cdecl
+      Out << "YAX";
+      // struct __block_literal *
+      Out << 'P';
+      // __ptr64
+      if (PointersAre64Bit)
+        Out << 'E';
+      Out << 'A';
+      mangleArtificalTagType(TTK_Struct,
+                             Discriminate("__block_literal", Discriminator,
+                                          ParameterDiscriminator));
+      Out << "@Z";
+
+      // If the effective context was a Record, we have fully mangled the
+      // qualified name and do not need to continue.
+      if (isa<RecordDecl>(DC))
+        break;
+      continue;
     } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
       mangleObjCMethodName(Method);
     } else if (isa<NamedDecl>(DC)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to