After much contemplation, I've decided that we probably shouldn't "unique"
__block object copy/dispose helpers for C++ objects with those for
different variables with completely different semantics simply because
they happen to both be no more aligned than a pointer.

Found by inspection.

Also, internalize most of the helper generation logic within CGBlocks.cpp,
and refactor it to fit my peculiar aesthetic sense.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128618 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index aa6a053..0f86257 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -247,9 +247,6 @@
     int GlobalUniqueCount;
   } Block;
 
-  llvm::DenseMap<uint64_t, llvm::Constant *> AssignCache;
-  llvm::DenseMap<uint64_t, llvm::Constant *> DestroyCache;
-
   /// @}
 public:
   CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
@@ -385,14 +382,35 @@
                                CastExpr::path_const_iterator PathBegin,
                                CastExpr::path_const_iterator PathEnd);
 
-  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T,
-                                       BlockFieldFlags flags,
-                                       unsigned Align,
-                                       const VarDecl *variable);
-  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T,
-                                          BlockFieldFlags flags,
-                                          unsigned Align,
-                                          const VarDecl *variable);
+  /// A pair of helper functions for a __block variable.
+  class ByrefHelpers : public llvm::FoldingSetNode {
+  public:
+    llvm::Constant *CopyHelper;
+    llvm::Constant *DisposeHelper;
+
+    /// The alignment of the field.  This is important because
+    /// different offsets to the field within the byref struct need to
+    /// have different helper functions.
+    CharUnits Alignment;
+
+    ByrefHelpers(CharUnits alignment) : Alignment(alignment) {}
+    virtual ~ByrefHelpers();
+
+    void Profile(llvm::FoldingSetNodeID &id) const {
+      id.AddInteger(Alignment.getQuantity());
+      profileImpl(id);
+    }
+    virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0;
+
+    virtual bool needsCopy() const { return true; }
+    virtual void emitCopy(CodeGenFunction &CGF,
+                          llvm::Value *dest, llvm::Value *src) = 0;
+
+    virtual bool needsDispose() const { return true; }
+    virtual void emitDispose(CodeGenFunction &CGF, llvm::Value *field) = 0;
+  };
+
+  llvm::FoldingSet<ByrefHelpers> ByrefHelpersCache;
 
   /// getUniqueBlockCount - Fetches the global unique block count.
   int getUniqueBlockCount() { return ++Block.GlobalUniqueCount; }