Author: compnerd
Date: Mon Jun 26 16:28:42 2017
New Revision: 306347

URL: http://llvm.org/viewvc/llvm-project?rev=306347&view=rev
Log:
AST: enhance mangling for blocks with MS ABI

When generating the decorated name for a static variable inside a
BlockDecl, construct a scope for the block invocation function that
homes the parameter. This allows for arbitrary nesting of the blocks
even if the variables are shadowed. Furthermore, using this for the name
allows for undname to properly undecorated the name for us. It shows up
as the synthetic __block_invocation function that the compiler emitted
in the local scope.

Added:
    cfe/trunk/test/CodeGenCXX/msabi-blocks.cpp
Modified:
    cfe/trunk/lib/AST/MicrosoftMangle.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=306347&r1=306346&r2=306347&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Mon Jun 26 16:28:42 2017
@@ -966,16 +966,71 @@ void MicrosoftCXXNameMangler::mangleNest
     }
 
     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)) {

Added: cfe/trunk/test/CodeGenCXX/msabi-blocks.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/msabi-blocks.cpp?rev=306347&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/msabi-blocks.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/msabi-blocks.cpp Mon Jun 26 16:28:42 2017
@@ -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
+


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to