blob: fa00bb7d2e8a5c2611b4fae32e3374feb7a5e828 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a class for OpenMP runtime code generation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
Alexey Bataev36bf0112015-03-10 05:15:26 +000016#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000018#include "clang/AST/StmtOpenMP.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "llvm/ADT/ArrayRef.h"
Alexey Bataevd74d0602014-10-13 06:02:40 +000020#include "llvm/IR/CallSite.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000021#include "llvm/IR/DerivedTypes.h"
22#include "llvm/IR/GlobalValue.h"
23#include "llvm/IR/Value.h"
24#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000025#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000026
27using namespace clang;
28using namespace CodeGen;
29
Benjamin Kramerc52193f2014-10-10 13:57:57 +000030namespace {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000031/// \brief Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000032class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
33public:
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000034 CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS)
35 : CGCapturedStmtInfo(CS, CR_OpenMP), Directive(D) {}
Alexey Bataev18095712014-10-10 12:19:54 +000036
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000037 CGOpenMPRegionInfo(const OMPExecutableDirective &D)
38 : CGCapturedStmtInfo(CR_OpenMP), Directive(D) {}
39
40 /// \brief Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000041 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000042 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000043
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000044 /// \brief Get an LValue for the current ThreadID variable.
Alexey Bataev18095712014-10-10 12:19:54 +000045 LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
46
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000047 /// \brief Emit the captured statement body.
48 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
49
Alexey Bataev18095712014-10-10 12:19:54 +000050 static bool classof(const CGCapturedStmtInfo *Info) {
51 return Info->getKind() == CR_OpenMP;
52 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000053protected:
54 /// \brief OpenMP executable directive associated with the region.
55 const OMPExecutableDirective &Directive;
56};
Alexey Bataev18095712014-10-10 12:19:54 +000057
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000058/// \brief API for captured statement code generation in OpenMP constructs.
59class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo {
60public:
61 CGOpenMPOutlinedRegionInfo(const OMPExecutableDirective &D,
62 const CapturedStmt &CS, const VarDecl *ThreadIDVar)
63 : CGOpenMPRegionInfo(D, CS), ThreadIDVar(ThreadIDVar) {
64 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
65 }
66 /// \brief Get a variable or parameter for storing global thread id
67 /// inside OpenMP construct.
68 virtual const VarDecl *getThreadIDVariable() const override {
69 return ThreadIDVar;
70 }
Alexey Bataev18095712014-10-10 12:19:54 +000071 /// \brief Get the name of the capture helper.
Benjamin Kramerc52193f2014-10-10 13:57:57 +000072 StringRef getHelperName() const override { return ".omp_outlined."; }
Alexey Bataev18095712014-10-10 12:19:54 +000073
74private:
75 /// \brief A variable or parameter storing global thread id for OpenMP
76 /// constructs.
77 const VarDecl *ThreadIDVar;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000078};
79
80/// \brief API for inlined captured statement code generation in OpenMP
81/// constructs.
82class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
83public:
84 CGOpenMPInlinedRegionInfo(const OMPExecutableDirective &D,
85 CodeGenFunction::CGCapturedStmtInfo *OldCSI)
86 : CGOpenMPRegionInfo(D), OldCSI(OldCSI),
87 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
88 // \brief Retrieve the value of the context parameter.
89 virtual llvm::Value *getContextValue() const override {
90 if (OuterRegionInfo)
91 return OuterRegionInfo->getContextValue();
92 llvm_unreachable("No context value for inlined OpenMP region");
93 }
94 /// \brief Lookup the captured field decl for a variable.
95 virtual const FieldDecl *lookup(const VarDecl *VD) const override {
96 if (OuterRegionInfo)
97 return OuterRegionInfo->lookup(VD);
98 llvm_unreachable("Trying to reference VarDecl that is neither local nor "
99 "captured in outer OpenMP region");
100 }
101 virtual FieldDecl *getThisFieldDecl() const override {
102 if (OuterRegionInfo)
103 return OuterRegionInfo->getThisFieldDecl();
104 return nullptr;
105 }
106 /// \brief Get a variable or parameter for storing global thread id
107 /// inside OpenMP construct.
108 virtual const VarDecl *getThreadIDVariable() const override {
109 if (OuterRegionInfo)
110 return OuterRegionInfo->getThreadIDVariable();
111 return nullptr;
112 }
113 /// \brief Get the name of the capture helper.
114 virtual StringRef getHelperName() const override {
115 llvm_unreachable("No helper name for inlined OpenMP construct");
116 }
117
118 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
119
120private:
121 /// \brief CodeGen info about outer OpenMP region.
122 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
123 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000124};
Benjamin Kramerc52193f2014-10-10 13:57:57 +0000125} // namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000126
127LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
128 return CGF.MakeNaturalAlignAddrLValue(
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000129 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
130 CGF.getContext().getPointerType(getThreadIDVariable()->getType()));
Alexey Bataev18095712014-10-10 12:19:54 +0000131}
132
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000133void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) {
Alexey Bataev435ad7b2014-10-10 09:48:26 +0000134 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +0000135 CGF.EmitOMPPrivateClause(Directive, PrivateScope);
Alexey Bataev435ad7b2014-10-10 09:48:26 +0000136 CGF.EmitOMPFirstprivateClause(Directive, PrivateScope);
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000137 if (PrivateScope.Privatize())
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000138 // Emit implicit barrier to synchronize threads and avoid data races.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000139 CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, Directive.getLocStart(),
140 /*IsExplicit=*/false);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000141 CGCapturedStmtInfo::EmitBody(CGF, S);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000142}
143
Alexey Bataev9959db52014-05-06 10:08:46 +0000144CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM)
145 : CGM(CGM), DefaultOpenMPPSource(nullptr) {
146 IdentTy = llvm::StructType::create(
147 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */,
148 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */,
Alexander Musmanfdfa8552014-09-11 08:10:57 +0000149 CGM.Int8PtrTy /* psource */, nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000150 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
Alexey Bataev23b69422014-06-18 07:08:49 +0000151 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
152 llvm::PointerType::getUnqual(CGM.Int32Ty)};
Alexey Bataev9959db52014-05-06 10:08:46 +0000153 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000154 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Alexey Bataev9959db52014-05-06 10:08:46 +0000155}
156
157llvm::Value *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000158CGOpenMPRuntime::emitOutlinedFunction(const OMPExecutableDirective &D,
159 const VarDecl *ThreadIDVar) {
Alexey Bataev18095712014-10-10 12:19:54 +0000160 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt());
161 CodeGenFunction CGF(CGM, true);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000162 CGOpenMPOutlinedRegionInfo CGInfo(D, *CS, ThreadIDVar);
Alexey Bataev18095712014-10-10 12:19:54 +0000163 CGF.CapturedStmtInfo = &CGInfo;
164 return CGF.GenerateCapturedStmtFunction(*CS);
165}
166
167llvm::Value *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000168CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000169 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000170 if (!Entry) {
171 if (!DefaultOpenMPPSource) {
172 // Initialize default location for psource field of ident_t structure of
173 // all ident_t objects. Format is ";file;function;line;column;;".
174 // Taken from
175 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
176 DefaultOpenMPPSource =
177 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
178 DefaultOpenMPPSource =
179 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
180 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000181 auto DefaultOpenMPLocation = new llvm::GlobalVariable(
182 CGM.getModule(), IdentTy, /*isConstant*/ true,
183 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
Alexey Bataev9959db52014-05-06 10:08:46 +0000184 DefaultOpenMPLocation->setUnnamedAddr(true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000185
186 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
Alexey Bataev23b69422014-06-18 07:08:49 +0000187 llvm::Constant *Values[] = {Zero,
188 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
189 Zero, Zero, DefaultOpenMPPSource};
Alexey Bataev9959db52014-05-06 10:08:46 +0000190 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
191 DefaultOpenMPLocation->setInitializer(Init);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000192 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +0000193 return DefaultOpenMPLocation;
194 }
195 return Entry;
196}
197
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000198llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
199 SourceLocation Loc,
200 OpenMPLocationFlags Flags) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000201 // If no debug info is generated - return global default location.
202 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
203 Loc.isInvalid())
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000204 return getOrCreateDefaultLocation(Flags);
Alexey Bataev9959db52014-05-06 10:08:46 +0000205
206 assert(CGF.CurFn && "No function in current CodeGenFunction.");
207
Alexey Bataev9959db52014-05-06 10:08:46 +0000208 llvm::Value *LocValue = nullptr;
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000209 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
210 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataev18095712014-10-10 12:19:54 +0000211 LocValue = I->second.DebugLoc;
Alexander Musmanc6388682014-12-15 07:07:06 +0000212 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
213 // GetOpenMPThreadID was called before this routine.
214 if (LocValue == nullptr) {
Alexey Bataev15007ba2014-05-07 06:18:01 +0000215 // Generate "ident_t .kmpc_loc.addr;"
216 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr");
Alexey Bataev9959db52014-05-06 10:08:46 +0000217 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
Alexey Bataev18095712014-10-10 12:19:54 +0000218 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
219 Elem.second.DebugLoc = AI;
Alexey Bataev9959db52014-05-06 10:08:46 +0000220 LocValue = AI;
221
222 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
223 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000224 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataev9959db52014-05-06 10:08:46 +0000225 llvm::ConstantExpr::getSizeOf(IdentTy),
226 CGM.PointerAlignInBytes);
227 }
228
229 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000230 auto *PSource =
Alexey Bataev9959db52014-05-06 10:08:46 +0000231 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
232
Alexey Bataevf002aca2014-05-30 05:48:40 +0000233 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
234 if (OMPDebugLoc == nullptr) {
235 SmallString<128> Buffer2;
236 llvm::raw_svector_ostream OS2(Buffer2);
237 // Build debug location
238 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
239 OS2 << ";" << PLoc.getFilename() << ";";
240 if (const FunctionDecl *FD =
241 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
242 OS2 << FD->getQualifiedNameAsString();
243 }
244 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
245 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
246 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +0000247 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000248 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataevf002aca2014-05-30 05:48:40 +0000249 CGF.Builder.CreateStore(OMPDebugLoc, PSource);
250
Alexey Bataev9959db52014-05-06 10:08:46 +0000251 return LocValue;
252}
253
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000254llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
255 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000256 assert(CGF.CurFn && "No function in current CodeGenFunction.");
257
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000258 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +0000259 // Check whether we've already cached a load of the thread id in this
260 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000261 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +0000262 if (I != OpenMPLocThreadIDMap.end()) {
263 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +0000264 if (ThreadID != nullptr)
265 return ThreadID;
266 }
267 if (auto OMPRegionInfo =
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000268 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000269 if (auto ThreadIDVar = OMPRegionInfo->getThreadIDVariable()) {
270 // Check if this an outlined function with thread id passed as argument.
271 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
272 auto RVal = CGF.EmitLoadOfLValue(LVal, Loc);
273 LVal = CGF.MakeNaturalAlignAddrLValue(RVal.getScalarVal(),
274 ThreadIDVar->getType());
275 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal();
276 // If value loaded in entry block, cache it and use it everywhere in
277 // function.
278 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
279 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
280 Elem.second.ThreadID = ThreadID;
281 }
282 return ThreadID;
Alexey Bataevd6c57552014-07-25 07:55:17 +0000283 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000284 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000285
286 // This is not an outlined function region - need to call __kmpc_int32
287 // kmpc_global_thread_num(ident_t *loc).
288 // Generate thread id value and cache this value for use across the
289 // function.
290 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
291 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
292 ThreadID =
293 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
294 emitUpdateLocation(CGF, Loc));
295 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
296 Elem.second.ThreadID = ThreadID;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000297 return ThreadID;
Alexey Bataev9959db52014-05-06 10:08:46 +0000298}
299
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000300void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000301 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataev03b340a2014-10-21 03:16:40 +0000302 if (OpenMPLocThreadIDMap.count(CGF.CurFn))
303 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +0000304}
305
306llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
307 return llvm::PointerType::getUnqual(IdentTy);
308}
309
310llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
311 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
312}
313
314llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000315CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) {
Alexey Bataev9959db52014-05-06 10:08:46 +0000316 llvm::Constant *RTLFn = nullptr;
317 switch (Function) {
318 case OMPRTL__kmpc_fork_call: {
319 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
320 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +0000321 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
322 getKmpc_MicroPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000323 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000324 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +0000325 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
326 break;
327 }
328 case OMPRTL__kmpc_global_thread_num: {
329 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +0000330 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataev9959db52014-05-06 10:08:46 +0000331 llvm::FunctionType *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +0000332 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +0000333 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
334 break;
335 }
Alexey Bataev97720002014-11-11 04:05:39 +0000336 case OMPRTL__kmpc_threadprivate_cached: {
337 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
338 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
339 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
340 CGM.VoidPtrTy, CGM.SizeTy,
341 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
342 llvm::FunctionType *FnTy =
343 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
344 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
345 break;
346 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000347 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000348 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
349 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000350 llvm::Type *TypeParams[] = {
351 getIdentTyPointerTy(), CGM.Int32Ty,
352 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
353 llvm::FunctionType *FnTy =
354 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
355 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
356 break;
357 }
Alexey Bataev97720002014-11-11 04:05:39 +0000358 case OMPRTL__kmpc_threadprivate_register: {
359 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
360 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
361 // typedef void *(*kmpc_ctor)(void *);
362 auto KmpcCtorTy =
363 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
364 /*isVarArg*/ false)->getPointerTo();
365 // typedef void *(*kmpc_cctor)(void *, void *);
366 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
367 auto KmpcCopyCtorTy =
368 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
369 /*isVarArg*/ false)->getPointerTo();
370 // typedef void (*kmpc_dtor)(void *);
371 auto KmpcDtorTy =
372 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
373 ->getPointerTo();
374 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
375 KmpcCopyCtorTy, KmpcDtorTy};
376 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
377 /*isVarArg*/ false);
378 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
379 break;
380 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000381 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +0000382 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
383 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000384 llvm::Type *TypeParams[] = {
385 getIdentTyPointerTy(), CGM.Int32Ty,
386 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
387 llvm::FunctionType *FnTy =
388 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
389 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
390 break;
391 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000392 case OMPRTL__kmpc_cancel_barrier: {
393 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
394 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000395 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
396 llvm::FunctionType *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000397 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
398 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000399 break;
400 }
Alexander Musmanc6388682014-12-15 07:07:06 +0000401 // Build __kmpc_for_static_init*(
402 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
403 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
404 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
405 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
406 case OMPRTL__kmpc_for_static_init_4: {
407 auto ITy = CGM.Int32Ty;
408 auto PtrTy = llvm::PointerType::getUnqual(ITy);
409 llvm::Type *TypeParams[] = {
410 getIdentTyPointerTy(), // loc
411 CGM.Int32Ty, // tid
412 CGM.Int32Ty, // schedtype
413 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
414 PtrTy, // p_lower
415 PtrTy, // p_upper
416 PtrTy, // p_stride
417 ITy, // incr
418 ITy // chunk
419 };
420 llvm::FunctionType *FnTy =
421 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
422 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4");
423 break;
424 }
425 case OMPRTL__kmpc_for_static_init_4u: {
426 auto ITy = CGM.Int32Ty;
427 auto PtrTy = llvm::PointerType::getUnqual(ITy);
428 llvm::Type *TypeParams[] = {
429 getIdentTyPointerTy(), // loc
430 CGM.Int32Ty, // tid
431 CGM.Int32Ty, // schedtype
432 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
433 PtrTy, // p_lower
434 PtrTy, // p_upper
435 PtrTy, // p_stride
436 ITy, // incr
437 ITy // chunk
438 };
439 llvm::FunctionType *FnTy =
440 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
441 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4u");
442 break;
443 }
444 case OMPRTL__kmpc_for_static_init_8: {
445 auto ITy = CGM.Int64Ty;
446 auto PtrTy = llvm::PointerType::getUnqual(ITy);
447 llvm::Type *TypeParams[] = {
448 getIdentTyPointerTy(), // loc
449 CGM.Int32Ty, // tid
450 CGM.Int32Ty, // schedtype
451 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
452 PtrTy, // p_lower
453 PtrTy, // p_upper
454 PtrTy, // p_stride
455 ITy, // incr
456 ITy // chunk
457 };
458 llvm::FunctionType *FnTy =
459 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
460 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8");
461 break;
462 }
463 case OMPRTL__kmpc_for_static_init_8u: {
464 auto ITy = CGM.Int64Ty;
465 auto PtrTy = llvm::PointerType::getUnqual(ITy);
466 llvm::Type *TypeParams[] = {
467 getIdentTyPointerTy(), // loc
468 CGM.Int32Ty, // tid
469 CGM.Int32Ty, // schedtype
470 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
471 PtrTy, // p_lower
472 PtrTy, // p_upper
473 PtrTy, // p_stride
474 ITy, // incr
475 ITy // chunk
476 };
477 llvm::FunctionType *FnTy =
478 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
479 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8u");
480 break;
481 }
482 case OMPRTL__kmpc_for_static_fini: {
483 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
484 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
485 llvm::FunctionType *FnTy =
486 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
488 break;
489 }
Alexey Bataevb2059782014-10-13 08:23:51 +0000490 case OMPRTL__kmpc_push_num_threads: {
491 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
492 // kmp_int32 num_threads)
493 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
494 CGM.Int32Ty};
495 llvm::FunctionType *FnTy =
496 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
497 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
498 break;
499 }
Alexey Bataevd74d0602014-10-13 06:02:40 +0000500 case OMPRTL__kmpc_serialized_parallel: {
501 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
502 // global_tid);
503 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
504 llvm::FunctionType *FnTy =
505 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
506 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
507 break;
508 }
509 case OMPRTL__kmpc_end_serialized_parallel: {
510 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
511 // global_tid);
512 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
513 llvm::FunctionType *FnTy =
514 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
515 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
516 break;
517 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000518 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000519 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000520 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
521 llvm::FunctionType *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +0000522 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +0000523 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
524 break;
525 }
Alexey Bataev8d690652014-12-04 07:23:53 +0000526 case OMPRTL__kmpc_master: {
527 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
528 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
529 llvm::FunctionType *FnTy =
530 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
531 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
532 break;
533 }
534 case OMPRTL__kmpc_end_master: {
535 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
536 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
537 llvm::FunctionType *FnTy =
538 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
539 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
540 break;
541 }
Alexey Bataev9f797f32015-02-05 05:57:51 +0000542 case OMPRTL__kmpc_omp_taskyield: {
543 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
544 // int end_part);
545 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
546 llvm::FunctionType *FnTy =
547 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
548 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
549 break;
550 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000551 case OMPRTL__kmpc_single: {
552 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
553 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
554 llvm::FunctionType *FnTy =
555 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
556 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
557 break;
558 }
559 case OMPRTL__kmpc_end_single: {
560 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
561 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
562 llvm::FunctionType *FnTy =
563 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
564 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
565 break;
566 }
Alexey Bataev9959db52014-05-06 10:08:46 +0000567 }
568 return RTLFn;
569}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000570
Alexey Bataev97720002014-11-11 04:05:39 +0000571llvm::Constant *
572CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
573 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000574 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy,
Alexey Bataev97720002014-11-11 04:05:39 +0000575 Twine(CGM.getMangledName(VD)) + ".cache.");
576}
577
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000578llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
579 const VarDecl *VD,
580 llvm::Value *VDAddr,
581 SourceLocation Loc) {
Alexey Bataev97720002014-11-11 04:05:39 +0000582 auto VarTy = VDAddr->getType()->getPointerElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000583 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev97720002014-11-11 04:05:39 +0000584 CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy),
585 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
586 getOrCreateThreadPrivateCache(VD)};
587 return CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000588 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000589}
590
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000591void CGOpenMPRuntime::emitThreadPrivateVarInit(
Alexey Bataev97720002014-11-11 04:05:39 +0000592 CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor,
593 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
594 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
595 // library.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000596 auto OMPLoc = emitUpdateLocation(CGF, Loc);
597 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +0000598 OMPLoc);
599 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
600 // to register constructor/destructor for variable.
601 llvm::Value *Args[] = {OMPLoc,
602 CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy),
603 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +0000604 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000605 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +0000606}
607
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000608llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
Alexey Bataev97720002014-11-11 04:05:39 +0000609 const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc,
610 bool PerformInit, CodeGenFunction *CGF) {
611 VD = VD->getDefinition(CGM.getContext());
612 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) {
613 ThreadPrivateWithDefinition.insert(VD);
614 QualType ASTTy = VD->getType();
615
616 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
617 auto Init = VD->getAnyInitializer();
618 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
619 // Generate function that re-emits the declaration's initializer into the
620 // threadprivate copy of the variable VD
621 CodeGenFunction CtorCGF(CGM);
622 FunctionArgList Args;
623 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
624 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
625 Args.push_back(&Dst);
626
627 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
628 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(),
629 /*isVariadic=*/false);
630 auto FTy = CGM.getTypes().GetFunctionType(FI);
631 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
632 FTy, ".__kmpc_global_ctor_.", Loc);
633 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
634 Args, SourceLocation());
635 auto ArgVal = CtorCGF.EmitLoadOfScalar(
636 CtorCGF.GetAddrOfLocalVar(&Dst),
637 /*Volatile=*/false, CGM.PointerAlignInBytes,
638 CGM.getContext().VoidPtrTy, Dst.getLocation());
639 auto Arg = CtorCGF.Builder.CreatePointerCast(
640 ArgVal,
641 CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy)));
642 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
643 /*IsInitializer=*/true);
644 ArgVal = CtorCGF.EmitLoadOfScalar(
645 CtorCGF.GetAddrOfLocalVar(&Dst),
646 /*Volatile=*/false, CGM.PointerAlignInBytes,
647 CGM.getContext().VoidPtrTy, Dst.getLocation());
648 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
649 CtorCGF.FinishFunction();
650 Ctor = Fn;
651 }
652 if (VD->getType().isDestructedType() != QualType::DK_none) {
653 // Generate function that emits destructor call for the threadprivate copy
654 // of the variable VD
655 CodeGenFunction DtorCGF(CGM);
656 FunctionArgList Args;
657 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(),
658 /*Id=*/nullptr, CGM.getContext().VoidPtrTy);
659 Args.push_back(&Dst);
660
661 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
662 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(),
663 /*isVariadic=*/false);
664 auto FTy = CGM.getTypes().GetFunctionType(FI);
665 auto Fn = CGM.CreateGlobalInitOrDestructFunction(
666 FTy, ".__kmpc_global_dtor_.", Loc);
667 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
668 SourceLocation());
669 auto ArgVal = DtorCGF.EmitLoadOfScalar(
670 DtorCGF.GetAddrOfLocalVar(&Dst),
671 /*Volatile=*/false, CGM.PointerAlignInBytes,
672 CGM.getContext().VoidPtrTy, Dst.getLocation());
673 DtorCGF.emitDestroy(ArgVal, ASTTy,
674 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
675 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
676 DtorCGF.FinishFunction();
677 Dtor = Fn;
678 }
679 // Do not emit init function if it is not required.
680 if (!Ctor && !Dtor)
681 return nullptr;
682
683 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
684 auto CopyCtorTy =
685 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
686 /*isVarArg=*/false)->getPointerTo();
687 // Copying constructor for the threadprivate variable.
688 // Must be NULL - reserved by runtime, but currently it requires that this
689 // parameter is always NULL. Otherwise it fires assertion.
690 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
691 if (Ctor == nullptr) {
692 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
693 /*isVarArg=*/false)->getPointerTo();
694 Ctor = llvm::Constant::getNullValue(CtorTy);
695 }
696 if (Dtor == nullptr) {
697 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
698 /*isVarArg=*/false)->getPointerTo();
699 Dtor = llvm::Constant::getNullValue(DtorTy);
700 }
701 if (!CGF) {
702 auto InitFunctionTy =
703 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
704 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction(
705 InitFunctionTy, ".__omp_threadprivate_init_.");
706 CodeGenFunction InitCGF(CGM);
707 FunctionArgList ArgList;
708 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
709 CGM.getTypes().arrangeNullaryFunction(), ArgList,
710 Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000711 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +0000712 InitCGF.FinishFunction();
713 return InitFunction;
714 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000715 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +0000716 }
717 return nullptr;
718}
719
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000720void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
721 llvm::Value *OutlinedFn,
722 llvm::Value *CapturedStruct) {
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000723 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
724 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000725 emitUpdateLocation(CGF, Loc),
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000726 CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument
727 // (there is only one additional argument - 'context')
728 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()),
729 CGF.EmitCastToVoidPtr(CapturedStruct)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000730 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000731 CGF.EmitRuntimeCall(RTLFn, Args);
732}
733
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000734void CGOpenMPRuntime::emitSerialCall(CodeGenFunction &CGF, SourceLocation Loc,
735 llvm::Value *OutlinedFn,
736 llvm::Value *CapturedStruct) {
737 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000738 // Build calls:
739 // __kmpc_serialized_parallel(&Loc, GTid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000740 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), ThreadID};
741 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel),
742 Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000743
744 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000745 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000746 auto Int32Ty =
747 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
748 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr");
749 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
750 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct};
751 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs);
752
753 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000754 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID};
755 CGF.EmitRuntimeCall(
756 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000757}
758
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +0000759// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +0000760// thread-ID variable (it is passed in a first argument of the outlined function
761// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
762// regular serial code region, get thread ID by calling kmp_int32
763// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
764// return the address of that temp.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000765llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
Alexey Bataevd74d0602014-10-13 06:02:40 +0000766 SourceLocation Loc) {
767 if (auto OMPRegionInfo =
768 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000769 if (OMPRegionInfo->getThreadIDVariable())
770 return CGF.EmitLoadOfLValue(OMPRegionInfo->getThreadIDVariableLValue(CGF),
771 Loc).getScalarVal();
772
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000773 auto ThreadID = getThreadID(CGF, Loc);
Alexey Bataevd74d0602014-10-13 06:02:40 +0000774 auto Int32Ty =
775 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
776 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
777 CGF.EmitStoreOfScalar(ThreadID,
778 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty));
779
780 return ThreadIDTemp;
781}
782
Alexey Bataev97720002014-11-11 04:05:39 +0000783llvm::Constant *
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000784CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty,
Alexey Bataev97720002014-11-11 04:05:39 +0000785 const llvm::Twine &Name) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000786 SmallString<256> Buffer;
787 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +0000788 Out << Name;
789 auto RuntimeName = Out.str();
David Blaikie13156b62014-11-19 03:06:06 +0000790 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first;
791 if (Elem.second) {
792 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +0000793 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +0000794 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +0000795 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000796
David Blaikie13156b62014-11-19 03:06:06 +0000797 return Elem.second = new llvm::GlobalVariable(
798 CGM.getModule(), Ty, /*IsConstant*/ false,
799 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
800 Elem.first());
Alexey Bataev97720002014-11-11 04:05:39 +0000801}
802
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000803llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev97720002014-11-11 04:05:39 +0000804 llvm::Twine Name(".gomp_critical_user_", CriticalName);
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000805 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var"));
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000806}
807
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000808void CGOpenMPRuntime::emitCriticalRegion(
Alexey Bataev75ddfab2014-12-01 11:32:38 +0000809 CodeGenFunction &CGF, StringRef CriticalName,
810 const std::function<void()> &CriticalOpGen, SourceLocation Loc) {
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000811 auto RegionLock = getCriticalRegionLock(CriticalName);
Alexey Bataev75ddfab2014-12-01 11:32:38 +0000812 // __kmpc_critical(ident_t *, gtid, Lock);
813 // CriticalOpGen();
814 // __kmpc_end_critical(ident_t *, gtid, Lock);
815 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000816 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
817 RegionLock};
818 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args);
Alexey Bataev75ddfab2014-12-01 11:32:38 +0000819 CriticalOpGen();
820 // Build a call to __kmpc_end_critical
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000821 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +0000822}
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000823
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000824static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond,
825 const std::function<void()> &BodyOpGen) {
Alexey Bataev8d690652014-12-04 07:23:53 +0000826 llvm::Value *CallBool = CGF.EmitScalarConversion(
827 IfCond,
828 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true),
829 CGF.getContext().BoolTy);
830
831 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
832 auto *ContBlock = CGF.createBasicBlock("omp_if.end");
833 // Generate the branch (If-stmt)
834 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
835 CGF.EmitBlock(ThenBlock);
836 BodyOpGen();
837 // Emit the rest of bblocks/branches
838 CGF.EmitBranch(ContBlock);
839 CGF.EmitBlock(ContBlock, true);
840}
841
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000842void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
843 const std::function<void()> &MasterOpGen,
844 SourceLocation Loc) {
Alexey Bataev8d690652014-12-04 07:23:53 +0000845 // if(__kmpc_master(ident_t *, gtid)) {
846 // MasterOpGen();
847 // __kmpc_end_master(ident_t *, gtid);
848 // }
849 // Prepare arguments and build a call to __kmpc_master
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000850 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
851 auto *IsMaster =
852 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args);
853 emitIfStmt(CGF, IsMaster, [&]() -> void {
Alexey Bataev8d690652014-12-04 07:23:53 +0000854 MasterOpGen();
855 // Build a call to __kmpc_end_master.
856 // OpenMP [1.2.2 OpenMP Language Terminology]
857 // For C/C++, an executable statement, possibly compound, with a single
858 // entry at the top and a single exit at the bottom, or an OpenMP construct.
859 // * Access to the structured block must not be the result of a branch.
860 // * The point of exit cannot be a branch out of the structured block.
861 // * The point of entry must not be a call to setjmp().
862 // * longjmp() and throw() must not violate the entry/exit criteria.
863 // * An expression statement, iteration statement, selection statement, or
864 // try block is considered to be a structured block if the corresponding
865 // compound statement obtained by enclosing it in { and } would be a
866 // structured block.
867 // It is analyzed in Sema, so we can just call __kmpc_end_master() on
868 // fallthrough rather than pushing a normal cleanup for it.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000869 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_master), Args);
Alexey Bataev8d690652014-12-04 07:23:53 +0000870 });
871}
872
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000873void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
874 SourceLocation Loc) {
Alexey Bataev9f797f32015-02-05 05:57:51 +0000875 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
876 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000877 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +0000878 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000879 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev9f797f32015-02-05 05:57:51 +0000880}
881
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000882void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
883 const std::function<void()> &SingleOpGen,
884 SourceLocation Loc) {
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000885 // if(__kmpc_single(ident_t *, gtid)) {
886 // SingleOpGen();
887 // __kmpc_end_single(ident_t *, gtid);
888 // }
889 // Prepare arguments and build a call to __kmpc_single
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000890 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
891 auto *IsSingle =
892 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args);
893 emitIfStmt(CGF, IsSingle, [&]() -> void {
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000894 SingleOpGen();
895 // Build a call to __kmpc_end_single.
896 // OpenMP [1.2.2 OpenMP Language Terminology]
897 // For C/C++, an executable statement, possibly compound, with a single
898 // entry at the top and a single exit at the bottom, or an OpenMP construct.
899 // * Access to the structured block must not be the result of a branch.
900 // * The point of exit cannot be a branch out of the structured block.
901 // * The point of entry must not be a call to setjmp().
902 // * longjmp() and throw() must not violate the entry/exit criteria.
903 // * An expression statement, iteration statement, selection statement, or
904 // try block is considered to be a structured block if the corresponding
905 // compound statement obtained by enclosing it in { and } would be a
906 // structured block.
907 // It is analyzed in Sema, so we can just call __kmpc_end_single() on
908 // fallthrough rather than pushing a normal cleanup for it.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000909 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_single), Args);
Alexey Bataev6956e2e2015-02-05 06:35:41 +0000910 });
911}
912
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000913void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
914 bool IsExplicit) {
Alexey Bataev8f7c1b02014-12-05 04:09:23 +0000915 // Build call __kmpc_cancel_barrier(loc, thread_id);
916 auto Flags = static_cast<OpenMPLocationFlags>(
917 OMP_IDENT_KMPC |
918 (IsExplicit ? OMP_IDENT_BARRIER_EXPL : OMP_IDENT_BARRIER_IMPL));
919 // Build call __kmpc_cancel_barrier(loc, thread_id);
920 // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this
921 // one provides the same functionality and adds initial support for
922 // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier()
923 // is provided default by the runtime library so it safe to make such
924 // replacement.
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000925 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
926 getThreadID(CGF, Loc)};
927 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000928}
929
Alexander Musmanc6388682014-12-15 07:07:06 +0000930/// \brief Schedule types for 'omp for' loops (these enumerators are taken from
931/// the enum sched_type in kmp.h).
932enum OpenMPSchedType {
933 /// \brief Lower bound for default (unordered) versions.
934 OMP_sch_lower = 32,
935 OMP_sch_static_chunked = 33,
936 OMP_sch_static = 34,
937 OMP_sch_dynamic_chunked = 35,
938 OMP_sch_guided_chunked = 36,
939 OMP_sch_runtime = 37,
940 OMP_sch_auto = 38,
941 /// \brief Lower bound for 'ordered' versions.
942 OMP_ord_lower = 64,
943 /// \brief Lower bound for 'nomerge' versions.
944 OMP_nm_lower = 160,
945};
946
947/// \brief Map the OpenMP loop schedule to the runtime enumeration.
948static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
949 bool Chunked) {
950 switch (ScheduleKind) {
951 case OMPC_SCHEDULE_static:
952 return Chunked ? OMP_sch_static_chunked : OMP_sch_static;
953 case OMPC_SCHEDULE_dynamic:
954 return OMP_sch_dynamic_chunked;
955 case OMPC_SCHEDULE_guided:
956 return OMP_sch_guided_chunked;
957 case OMPC_SCHEDULE_auto:
958 return OMP_sch_auto;
959 case OMPC_SCHEDULE_runtime:
960 return OMP_sch_runtime;
961 case OMPC_SCHEDULE_unknown:
962 assert(!Chunked && "chunk was specified but schedule kind not known");
963 return OMP_sch_static;
964 }
965 llvm_unreachable("Unexpected runtime schedule");
966}
967
968bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
969 bool Chunked) const {
970 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
971 return Schedule == OMP_sch_static;
972}
973
Alexander Musmandf7a8e22015-01-22 08:49:35 +0000974bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
975 auto Schedule = getRuntimeSchedule(ScheduleKind, /* Chunked */ false);
976 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
977 return Schedule != OMP_sch_static;
978}
979
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000980void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc,
981 OpenMPScheduleClauseKind ScheduleKind,
982 unsigned IVSize, bool IVSigned,
983 llvm::Value *IL, llvm::Value *LB,
984 llvm::Value *UB, llvm::Value *ST,
985 llvm::Value *Chunk) {
Alexander Musmanc6388682014-12-15 07:07:06 +0000986 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunk != nullptr);
987 // Call __kmpc_for_static_init(
988 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
989 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
990 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
991 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
992 // TODO: Implement dynamic schedule.
993
994 // If the Chunk was not specified in the clause - use default value 1.
995 if (Chunk == nullptr)
996 Chunk = CGF.Builder.getIntN(IVSize, /*C*/ 1);
997
998 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +0000999 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc),
Alexander Musmanc6388682014-12-15 07:07:06 +00001000 CGF.Builder.getInt32(Schedule), // Schedule type
1001 IL, // &isLastIter
1002 LB, // &LB
1003 UB, // &UB
1004 ST, // &Stride
1005 CGF.Builder.getIntN(IVSize, 1), // Incr
1006 Chunk // Chunk
1007 };
1008 assert((IVSize == 32 || IVSize == 64) &&
1009 "Index size is not compatible with the omp runtime");
1010 auto F = IVSize == 32 ? (IVSigned ? OMPRTL__kmpc_for_static_init_4
1011 : OMPRTL__kmpc_for_static_init_4u)
1012 : (IVSigned ? OMPRTL__kmpc_for_static_init_8
1013 : OMPRTL__kmpc_for_static_init_8u);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001014 CGF.EmitRuntimeCall(createRuntimeFunction(F), Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001015}
1016
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001017void CGOpenMPRuntime::emitForFinish(CodeGenFunction &CGF, SourceLocation Loc,
1018 OpenMPScheduleClauseKind ScheduleKind) {
Alexander Musmanc6388682014-12-15 07:07:06 +00001019 assert((ScheduleKind == OMPC_SCHEDULE_static ||
1020 ScheduleKind == OMPC_SCHEDULE_unknown) &&
1021 "Non-static schedule kinds are not yet implemented");
1022 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001023 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC),
1024 getThreadID(CGF, Loc)};
1025 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
1026 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00001027}
1028
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001029void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
1030 llvm::Value *NumThreads,
1031 SourceLocation Loc) {
Alexey Bataevb2059782014-10-13 08:23:51 +00001032 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
1033 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001034 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00001035 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001036 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
1037 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00001038}
1039
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001040void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
1041 SourceLocation Loc) {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001042 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001043 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
1044 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001045}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001046
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001047InlinedOpenMPRegionRAII::InlinedOpenMPRegionRAII(
1048 CodeGenFunction &CGF, const OMPExecutableDirective &D)
1049 : CGF(CGF) {
1050 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(D, CGF.CapturedStmtInfo);
Alexey Bataev36bf0112015-03-10 05:15:26 +00001051 // 1.2.2 OpenMP Language Terminology
1052 // Structured block - An executable statement with a single entry at the
1053 // top and a single exit at the bottom.
1054 // The point of exit cannot be a branch out of the structured block.
1055 // longjmp() and throw() must not violate the entry/exit criteria.
1056 CGF.EHStack.pushTerminate();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001057}
1058
1059InlinedOpenMPRegionRAII::~InlinedOpenMPRegionRAII() {
Alexey Bataev36bf0112015-03-10 05:15:26 +00001060 CGF.EHStack.popTerminate();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001061 auto *OldCSI =
1062 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
1063 delete CGF.CapturedStmtInfo;
1064 CGF.CapturedStmtInfo = OldCSI;
1065}
1066