[OPENMP] Codegen for 'omp critical' directive.
This patch adds codegen for constructs:
#pragma omp critical [name]
<body>

It generates global variable ".gomp_critical_user_[name].var" of type int32[8]. Then it generates library call "kmpc_critical(loc, gtid, .gomp_critical_user_[name].var)", code for <body> statement and final call "kmpc_end_critical(loc, gtid, .gomp_critical_user_[name].var)".
Differential Revision: http://reviews.llvm.org/D5202

llvm-svn: 218239
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h
index 3759a77..d32c43a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.h
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.h
@@ -16,6 +16,7 @@
 
 #include "clang/AST/Type.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 
@@ -27,6 +28,7 @@
 class Function;
 class Module;
 class StructLayout;
+class ArrayType;
 class FunctionType;
 class StructType;
 class Type;
@@ -67,8 +69,14 @@
     // Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
     // microtask, ...);
     OMPRTL__kmpc_fork_call,
-    // Call to kmp_int32 kmpc_global_thread_num(ident_t *loc);
-    OMPRTL__kmpc_global_thread_num
+    // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
+    OMPRTL__kmpc_global_thread_num,
+    // Call to void __kmpc_critical(ident_t ∗loc, kmp_int32 global_tid,
+    // kmp_critical_name ∗crit);
+    OMPRTL__kmpc_critical,
+    // Call to void __kmpc_end_critical(ident_t ∗loc, kmp_int32 global_tid,
+    // kmp_critical_name ∗crit);
+    OMPRTL__kmpc_end_critical
   };
 
 private:
@@ -134,10 +142,15 @@
   /// \brief Map of local gtid and functions.
   typedef llvm::DenseMap<llvm::Function *, llvm::Value *> OpenMPGtidMapTy;
   OpenMPGtidMapTy OpenMPGtidMap;
+  /// \brief Type kmp_critical_name, originally defined as typedef kmp_int32
+  /// kmp_critical_name[8];
+  llvm::ArrayType *KmpCriticalNameTy;
+  /// \brief Map of critical regions names and the corresponding lock objects.
+  llvm::StringMap<llvm::Value *, llvm::BumpPtrAllocator> CriticalRegionVarNames;
 
 public:
   explicit CGOpenMPRuntime(CodeGenModule &CGM);
-  ~CGOpenMPRuntime() {}
+  virtual ~CGOpenMPRuntime() {}
 
   /// \brief Cleans up references to the objects in finished function.
   /// \param CGF Reference to finished CodeGenFunction.
@@ -170,6 +183,31 @@
   /// \param Function OpenMP runtime function.
   /// \return Specified function.
   llvm::Constant *CreateRuntimeFunction(OpenMPRTLFunction Function);
+
+  /// \brief Returns corresponding lock object for the specified critical region
+  /// name. If the lock object does not exist it is created, otherwise the
+  /// reference to the existing copy is returned.
+  llvm::Value *GetCriticalRegionLock(StringRef CriticalName);
+
+  /// \brief Emits start of the critical region by calling void
+  /// __kmpc_critical(ident_t ∗loc, kmp_int32 global_tid, kmp_critical_name
+  /// ∗\a RegionLock)
+  /// \param CGF Reference to current CodeGenFunction.
+  /// \param RegionLock The lock object for critical region.
+  /// \param Loc Location of the construct.
+  virtual void EmitOMPCriticalRegionStart(CodeGenFunction &CGF,
+                                          llvm::Value *RegionLock,
+                                          SourceLocation Loc);
+
+  /// \brief Emits end of the critical region by calling void
+  /// __kmpc_end_critical(ident_t ∗loc, kmp_int32 global_tid, kmp_critical_name
+  /// ∗\a RegionLock)
+  /// \param CGF Reference to current CodeGenFunction.
+  /// \param RegionLock The lock object for critical region.
+  /// \param Loc Location of the construct.
+  virtual void EmitOMPCriticalRegionEnd(CodeGenFunction &CGF,
+                                        llvm::Value *RegionLock,
+                                        SourceLocation Loc);
 };
 } // namespace CodeGen
 } // namespace clang