1 //===----- 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" 16 #include "CGCleanup.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/AST/StmtOpenMP.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/IR/CallSite.h" 21 #include "llvm/IR/DerivedTypes.h" 22 #include "llvm/IR/GlobalValue.h" 23 #include "llvm/IR/Value.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <cassert> 26 27 using namespace clang; 28 using namespace CodeGen; 29 30 namespace { 31 /// \brief Base class for handling code generation inside OpenMP regions. 32 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 33 public: 34 CGOpenMPRegionInfo(const OMPExecutableDirective &D, const CapturedStmt &CS) 35 : CGCapturedStmtInfo(CS, CR_OpenMP), Directive(D) {} 36 37 CGOpenMPRegionInfo(const OMPExecutableDirective &D) 38 : CGCapturedStmtInfo(CR_OpenMP), Directive(D) {} 39 40 /// \brief Get a variable or parameter for storing global thread id 41 /// inside OpenMP construct. 42 virtual const VarDecl *getThreadIDVariable() const = 0; 43 44 /// \brief Get an LValue for the current ThreadID variable. 45 /// \return LValue for thread id variable. This LValue always has type int32*. 46 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 47 48 /// \brief Emit the captured statement body. 49 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 50 51 static bool classof(const CGCapturedStmtInfo *Info) { 52 return Info->getKind() == CR_OpenMP; 53 } 54 protected: 55 /// \brief OpenMP executable directive associated with the region. 56 const OMPExecutableDirective &Directive; 57 }; 58 59 /// \brief API for captured statement code generation in OpenMP constructs. 60 class CGOpenMPOutlinedRegionInfo : public CGOpenMPRegionInfo { 61 public: 62 CGOpenMPOutlinedRegionInfo(const OMPExecutableDirective &D, 63 const CapturedStmt &CS, const VarDecl *ThreadIDVar) 64 : CGOpenMPRegionInfo(D, CS), ThreadIDVar(ThreadIDVar) { 65 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 66 } 67 /// \brief Get a variable or parameter for storing global thread id 68 /// inside OpenMP construct. 69 virtual const VarDecl *getThreadIDVariable() const override { 70 return ThreadIDVar; 71 } 72 /// \brief Get the name of the capture helper. 73 StringRef getHelperName() const override { return ".omp_outlined."; } 74 75 private: 76 /// \brief A variable or parameter storing global thread id for OpenMP 77 /// constructs. 78 const VarDecl *ThreadIDVar; 79 }; 80 81 /// \brief API for captured statement code generation in OpenMP constructs. 82 class CGOpenMPTaskOutlinedRegionInfo : public CGOpenMPRegionInfo { 83 public: 84 CGOpenMPTaskOutlinedRegionInfo(const OMPExecutableDirective &D, 85 const CapturedStmt &CS, 86 const VarDecl *ThreadIDVar, 87 const VarDecl *PartIDVar) 88 : CGOpenMPRegionInfo(D, CS), ThreadIDVar(ThreadIDVar), 89 PartIDVar(PartIDVar) { 90 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 91 } 92 /// \brief Get a variable or parameter for storing global thread id 93 /// inside OpenMP construct. 94 virtual const VarDecl *getThreadIDVariable() const override { 95 return ThreadIDVar; 96 } 97 98 /// \brief Get an LValue for the current ThreadID variable. 99 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 100 101 /// \brief Emit the captured statement body. 102 virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 103 104 /// \brief Get the name of the capture helper. 105 StringRef getHelperName() const override { return ".omp_outlined."; } 106 107 private: 108 /// \brief A variable or parameter storing global thread id for OpenMP 109 /// constructs. 110 const VarDecl *ThreadIDVar; 111 /// \brief A variable or parameter storing part id for OpenMP tasking 112 /// constructs. 113 const VarDecl *PartIDVar; 114 }; 115 116 /// \brief API for inlined captured statement code generation in OpenMP 117 /// constructs. 118 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 119 public: 120 CGOpenMPInlinedRegionInfo(const OMPExecutableDirective &D, 121 CodeGenFunction::CGCapturedStmtInfo *OldCSI) 122 : CGOpenMPRegionInfo(D), OldCSI(OldCSI), 123 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 124 // \brief Retrieve the value of the context parameter. 125 virtual llvm::Value *getContextValue() const override { 126 if (OuterRegionInfo) 127 return OuterRegionInfo->getContextValue(); 128 llvm_unreachable("No context value for inlined OpenMP region"); 129 } 130 /// \brief Lookup the captured field decl for a variable. 131 virtual const FieldDecl *lookup(const VarDecl *VD) const override { 132 if (OuterRegionInfo) 133 return OuterRegionInfo->lookup(VD); 134 llvm_unreachable("Trying to reference VarDecl that is neither local nor " 135 "captured in outer OpenMP region"); 136 } 137 virtual FieldDecl *getThisFieldDecl() const override { 138 if (OuterRegionInfo) 139 return OuterRegionInfo->getThisFieldDecl(); 140 return nullptr; 141 } 142 /// \brief Get a variable or parameter for storing global thread id 143 /// inside OpenMP construct. 144 virtual const VarDecl *getThreadIDVariable() const override { 145 if (OuterRegionInfo) 146 return OuterRegionInfo->getThreadIDVariable(); 147 return nullptr; 148 } 149 150 /// \brief Get the name of the capture helper. 151 virtual StringRef getHelperName() const override { 152 llvm_unreachable("No helper name for inlined OpenMP construct"); 153 } 154 155 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 156 157 private: 158 /// \brief CodeGen info about outer OpenMP region. 159 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 160 CGOpenMPRegionInfo *OuterRegionInfo; 161 }; 162 } // namespace 163 164 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 165 return CGF.MakeNaturalAlignAddrLValue( 166 CGF.Builder.CreateAlignedLoad( 167 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 168 CGF.PointerAlignInBytes), 169 getThreadIDVariable() 170 ->getType() 171 ->castAs<PointerType>() 172 ->getPointeeType()); 173 } 174 175 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) { 176 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 177 CGF.EmitOMPPrivateClause(Directive, PrivateScope); 178 CGF.EmitOMPFirstprivateClause(Directive, PrivateScope); 179 if (PrivateScope.Privatize()) 180 // Emit implicit barrier to synchronize threads and avoid data races. 181 CGF.CGM.getOpenMPRuntime().emitBarrierCall(CGF, Directive.getLocStart(), 182 /*IsExplicit=*/false); 183 CGCapturedStmtInfo::EmitBody(CGF, S); 184 } 185 186 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 187 CodeGenFunction &CGF) { 188 return CGF.MakeNaturalAlignAddrLValue( 189 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 190 getThreadIDVariable()->getType()); 191 } 192 193 void CGOpenMPTaskOutlinedRegionInfo::EmitBody(CodeGenFunction &CGF, 194 const Stmt *S) { 195 if (PartIDVar) { 196 // TODO: emit code for untied tasks. 197 } 198 CGCapturedStmtInfo::EmitBody(CGF, S); 199 } 200 201 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 202 : CGM(CGM), DefaultOpenMPPSource(nullptr), KmpRoutineEntryPtrTy(nullptr) { 203 IdentTy = llvm::StructType::create( 204 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 205 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 206 CGM.Int8PtrTy /* psource */, nullptr); 207 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 208 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 209 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 210 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 211 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 212 } 213 214 llvm::Value * 215 CGOpenMPRuntime::emitOutlinedFunction(const OMPExecutableDirective &D, 216 const VarDecl *ThreadIDVar) { 217 assert(ThreadIDVar->getType()->isPointerType() && 218 "thread id variable must be of type kmp_int32 *"); 219 const CapturedStmt *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 220 CodeGenFunction CGF(CGM, true); 221 CGOpenMPOutlinedRegionInfo CGInfo(D, *CS, ThreadIDVar); 222 CGF.CapturedStmtInfo = &CGInfo; 223 return CGF.GenerateCapturedStmtFunction(*CS); 224 } 225 226 llvm::Value * 227 CGOpenMPRuntime::emitTaskOutlinedFunction(const OMPExecutableDirective &D, 228 const VarDecl *ThreadIDVar, 229 const VarDecl *PartIDVar) { 230 assert(!ThreadIDVar->getType()->isPointerType() && 231 "thread id variable must be of type kmp_int32 for tasks"); 232 auto *CS = cast<CapturedStmt>(D.getAssociatedStmt()); 233 CodeGenFunction CGF(CGM, true); 234 CGOpenMPTaskOutlinedRegionInfo CGInfo(D, *CS, ThreadIDVar, PartIDVar); 235 CGF.CapturedStmtInfo = &CGInfo; 236 return CGF.GenerateCapturedStmtFunction(*CS); 237 } 238 239 llvm::Value * 240 CGOpenMPRuntime::getOrCreateDefaultLocation(OpenMPLocationFlags Flags) { 241 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 242 if (!Entry) { 243 if (!DefaultOpenMPPSource) { 244 // Initialize default location for psource field of ident_t structure of 245 // all ident_t objects. Format is ";file;function;line;column;;". 246 // Taken from 247 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 248 DefaultOpenMPPSource = 249 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;"); 250 DefaultOpenMPPSource = 251 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 252 } 253 auto DefaultOpenMPLocation = new llvm::GlobalVariable( 254 CGM.getModule(), IdentTy, /*isConstant*/ true, 255 llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr); 256 DefaultOpenMPLocation->setUnnamedAddr(true); 257 258 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 259 llvm::Constant *Values[] = {Zero, 260 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 261 Zero, Zero, DefaultOpenMPPSource}; 262 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 263 DefaultOpenMPLocation->setInitializer(Init); 264 OpenMPDefaultLocMap[Flags] = DefaultOpenMPLocation; 265 return DefaultOpenMPLocation; 266 } 267 return Entry; 268 } 269 270 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 271 SourceLocation Loc, 272 OpenMPLocationFlags Flags) { 273 // If no debug info is generated - return global default location. 274 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo || 275 Loc.isInvalid()) 276 return getOrCreateDefaultLocation(Flags); 277 278 assert(CGF.CurFn && "No function in current CodeGenFunction."); 279 280 llvm::Value *LocValue = nullptr; 281 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 282 if (I != OpenMPLocThreadIDMap.end()) 283 LocValue = I->second.DebugLoc; 284 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 285 // GetOpenMPThreadID was called before this routine. 286 if (LocValue == nullptr) { 287 // Generate "ident_t .kmpc_loc.addr;" 288 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr"); 289 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy)); 290 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 291 Elem.second.DebugLoc = AI; 292 LocValue = AI; 293 294 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 295 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 296 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 297 llvm::ConstantExpr::getSizeOf(IdentTy), 298 CGM.PointerAlignInBytes); 299 } 300 301 // char **psource = &.kmpc_loc_<flags>.addr.psource; 302 auto *PSource = 303 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource); 304 305 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 306 if (OMPDebugLoc == nullptr) { 307 SmallString<128> Buffer2; 308 llvm::raw_svector_ostream OS2(Buffer2); 309 // Build debug location 310 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 311 OS2 << ";" << PLoc.getFilename() << ";"; 312 if (const FunctionDecl *FD = 313 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 314 OS2 << FD->getQualifiedNameAsString(); 315 } 316 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 317 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 318 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 319 } 320 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 321 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 322 323 return LocValue; 324 } 325 326 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 327 SourceLocation Loc) { 328 assert(CGF.CurFn && "No function in current CodeGenFunction."); 329 330 llvm::Value *ThreadID = nullptr; 331 // Check whether we've already cached a load of the thread id in this 332 // function. 333 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 334 if (I != OpenMPLocThreadIDMap.end()) { 335 ThreadID = I->second.ThreadID; 336 if (ThreadID != nullptr) 337 return ThreadID; 338 } 339 if (auto OMPRegionInfo = 340 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 341 if (OMPRegionInfo->getThreadIDVariable()) { 342 // Check if this an outlined function with thread id passed as argument. 343 auto LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 344 ThreadID = CGF.EmitLoadOfLValue(LVal, Loc).getScalarVal(); 345 // If value loaded in entry block, cache it and use it everywhere in 346 // function. 347 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 348 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 349 Elem.second.ThreadID = ThreadID; 350 } 351 return ThreadID; 352 } 353 } 354 355 // This is not an outlined function region - need to call __kmpc_int32 356 // kmpc_global_thread_num(ident_t *loc). 357 // Generate thread id value and cache this value for use across the 358 // function. 359 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 360 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 361 ThreadID = 362 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 363 emitUpdateLocation(CGF, Loc)); 364 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 365 Elem.second.ThreadID = ThreadID; 366 return ThreadID; 367 } 368 369 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 370 assert(CGF.CurFn && "No function in current CodeGenFunction."); 371 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) 372 OpenMPLocThreadIDMap.erase(CGF.CurFn); 373 } 374 375 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 376 return llvm::PointerType::getUnqual(IdentTy); 377 } 378 379 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 380 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 381 } 382 383 llvm::Constant * 384 CGOpenMPRuntime::createRuntimeFunction(OpenMPRTLFunction Function) { 385 llvm::Constant *RTLFn = nullptr; 386 switch (Function) { 387 case OMPRTL__kmpc_fork_call: { 388 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 389 // microtask, ...); 390 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 391 getKmpc_MicroPointerTy()}; 392 llvm::FunctionType *FnTy = 393 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 394 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 395 break; 396 } 397 case OMPRTL__kmpc_global_thread_num: { 398 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 399 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 400 llvm::FunctionType *FnTy = 401 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 402 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 403 break; 404 } 405 case OMPRTL__kmpc_threadprivate_cached: { 406 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 407 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 408 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 409 CGM.VoidPtrTy, CGM.SizeTy, 410 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 411 llvm::FunctionType *FnTy = 412 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 413 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 414 break; 415 } 416 case OMPRTL__kmpc_critical: { 417 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 418 // kmp_critical_name *crit); 419 llvm::Type *TypeParams[] = { 420 getIdentTyPointerTy(), CGM.Int32Ty, 421 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 422 llvm::FunctionType *FnTy = 423 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 424 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 425 break; 426 } 427 case OMPRTL__kmpc_threadprivate_register: { 428 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 429 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 430 // typedef void *(*kmpc_ctor)(void *); 431 auto KmpcCtorTy = 432 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 433 /*isVarArg*/ false)->getPointerTo(); 434 // typedef void *(*kmpc_cctor)(void *, void *); 435 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 436 auto KmpcCopyCtorTy = 437 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 438 /*isVarArg*/ false)->getPointerTo(); 439 // typedef void (*kmpc_dtor)(void *); 440 auto KmpcDtorTy = 441 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 442 ->getPointerTo(); 443 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 444 KmpcCopyCtorTy, KmpcDtorTy}; 445 auto FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 446 /*isVarArg*/ false); 447 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 448 break; 449 } 450 case OMPRTL__kmpc_end_critical: { 451 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 452 // kmp_critical_name *crit); 453 llvm::Type *TypeParams[] = { 454 getIdentTyPointerTy(), CGM.Int32Ty, 455 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 456 llvm::FunctionType *FnTy = 457 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 458 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 459 break; 460 } 461 case OMPRTL__kmpc_cancel_barrier: { 462 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 463 // global_tid); 464 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 465 llvm::FunctionType *FnTy = 466 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 467 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 468 break; 469 } 470 // Build __kmpc_for_static_init*( 471 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 472 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 473 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 474 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 475 case OMPRTL__kmpc_for_static_init_4: { 476 auto ITy = CGM.Int32Ty; 477 auto PtrTy = llvm::PointerType::getUnqual(ITy); 478 llvm::Type *TypeParams[] = { 479 getIdentTyPointerTy(), // loc 480 CGM.Int32Ty, // tid 481 CGM.Int32Ty, // schedtype 482 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 483 PtrTy, // p_lower 484 PtrTy, // p_upper 485 PtrTy, // p_stride 486 ITy, // incr 487 ITy // chunk 488 }; 489 llvm::FunctionType *FnTy = 490 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 491 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4"); 492 break; 493 } 494 case OMPRTL__kmpc_for_static_init_4u: { 495 auto ITy = CGM.Int32Ty; 496 auto PtrTy = llvm::PointerType::getUnqual(ITy); 497 llvm::Type *TypeParams[] = { 498 getIdentTyPointerTy(), // loc 499 CGM.Int32Ty, // tid 500 CGM.Int32Ty, // schedtype 501 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 502 PtrTy, // p_lower 503 PtrTy, // p_upper 504 PtrTy, // p_stride 505 ITy, // incr 506 ITy // chunk 507 }; 508 llvm::FunctionType *FnTy = 509 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 510 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_4u"); 511 break; 512 } 513 case OMPRTL__kmpc_for_static_init_8: { 514 auto ITy = CGM.Int64Ty; 515 auto PtrTy = llvm::PointerType::getUnqual(ITy); 516 llvm::Type *TypeParams[] = { 517 getIdentTyPointerTy(), // loc 518 CGM.Int32Ty, // tid 519 CGM.Int32Ty, // schedtype 520 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 521 PtrTy, // p_lower 522 PtrTy, // p_upper 523 PtrTy, // p_stride 524 ITy, // incr 525 ITy // chunk 526 }; 527 llvm::FunctionType *FnTy = 528 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 529 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8"); 530 break; 531 } 532 case OMPRTL__kmpc_for_static_init_8u: { 533 auto ITy = CGM.Int64Ty; 534 auto PtrTy = llvm::PointerType::getUnqual(ITy); 535 llvm::Type *TypeParams[] = { 536 getIdentTyPointerTy(), // loc 537 CGM.Int32Ty, // tid 538 CGM.Int32Ty, // schedtype 539 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 540 PtrTy, // p_lower 541 PtrTy, // p_upper 542 PtrTy, // p_stride 543 ITy, // incr 544 ITy // chunk 545 }; 546 llvm::FunctionType *FnTy = 547 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 548 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_init_8u"); 549 break; 550 } 551 case OMPRTL__kmpc_for_static_fini: { 552 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 553 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 554 llvm::FunctionType *FnTy = 555 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 556 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 557 break; 558 } 559 case OMPRTL__kmpc_push_num_threads: { 560 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 561 // kmp_int32 num_threads) 562 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 563 CGM.Int32Ty}; 564 llvm::FunctionType *FnTy = 565 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 566 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 567 break; 568 } 569 case OMPRTL__kmpc_serialized_parallel: { 570 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 571 // global_tid); 572 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 573 llvm::FunctionType *FnTy = 574 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 575 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 576 break; 577 } 578 case OMPRTL__kmpc_end_serialized_parallel: { 579 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 580 // global_tid); 581 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 582 llvm::FunctionType *FnTy = 583 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 584 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 585 break; 586 } 587 case OMPRTL__kmpc_flush: { 588 // Build void __kmpc_flush(ident_t *loc); 589 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 590 llvm::FunctionType *FnTy = 591 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 592 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 593 break; 594 } 595 case OMPRTL__kmpc_master: { 596 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 597 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 598 llvm::FunctionType *FnTy = 599 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 600 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 601 break; 602 } 603 case OMPRTL__kmpc_end_master: { 604 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 605 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 606 llvm::FunctionType *FnTy = 607 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 608 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 609 break; 610 } 611 case OMPRTL__kmpc_omp_taskyield: { 612 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 613 // int end_part); 614 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 615 llvm::FunctionType *FnTy = 616 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 617 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 618 break; 619 } 620 case OMPRTL__kmpc_single: { 621 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 622 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 623 llvm::FunctionType *FnTy = 624 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 625 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 626 break; 627 } 628 case OMPRTL__kmpc_end_single: { 629 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 630 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 631 llvm::FunctionType *FnTy = 632 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 633 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 634 break; 635 } 636 case OMPRTL__kmpc_omp_task_alloc: { 637 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 638 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 639 // kmp_routine_entry_t *task_entry); 640 assert(KmpRoutineEntryPtrTy != nullptr && 641 "Type kmp_routine_entry_t must be created."); 642 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 643 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 644 // Return void * and then cast to particular kmp_task_t type. 645 llvm::FunctionType *FnTy = 646 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 647 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 648 break; 649 } 650 case OMPRTL__kmpc_omp_task: { 651 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 652 // *new_task); 653 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 654 CGM.VoidPtrTy}; 655 llvm::FunctionType *FnTy = 656 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 657 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 658 break; 659 } 660 } 661 return RTLFn; 662 } 663 664 llvm::Constant * 665 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 666 // Lookup the entry, lazily creating it if necessary. 667 return getOrCreateInternalVariable(CGM.Int8PtrPtrTy, 668 Twine(CGM.getMangledName(VD)) + ".cache."); 669 } 670 671 llvm::Value *CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 672 const VarDecl *VD, 673 llvm::Value *VDAddr, 674 SourceLocation Loc) { 675 auto VarTy = VDAddr->getType()->getPointerElementType(); 676 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 677 CGF.Builder.CreatePointerCast(VDAddr, CGM.Int8PtrTy), 678 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 679 getOrCreateThreadPrivateCache(VD)}; 680 return CGF.EmitRuntimeCall( 681 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args); 682 } 683 684 void CGOpenMPRuntime::emitThreadPrivateVarInit( 685 CodeGenFunction &CGF, llvm::Value *VDAddr, llvm::Value *Ctor, 686 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 687 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 688 // library. 689 auto OMPLoc = emitUpdateLocation(CGF, Loc); 690 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 691 OMPLoc); 692 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 693 // to register constructor/destructor for variable. 694 llvm::Value *Args[] = {OMPLoc, 695 CGF.Builder.CreatePointerCast(VDAddr, CGM.VoidPtrTy), 696 Ctor, CopyCtor, Dtor}; 697 CGF.EmitRuntimeCall( 698 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 699 } 700 701 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 702 const VarDecl *VD, llvm::Value *VDAddr, SourceLocation Loc, 703 bool PerformInit, CodeGenFunction *CGF) { 704 VD = VD->getDefinition(CGM.getContext()); 705 if (VD && ThreadPrivateWithDefinition.count(VD) == 0) { 706 ThreadPrivateWithDefinition.insert(VD); 707 QualType ASTTy = VD->getType(); 708 709 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 710 auto Init = VD->getAnyInitializer(); 711 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 712 // Generate function that re-emits the declaration's initializer into the 713 // threadprivate copy of the variable VD 714 CodeGenFunction CtorCGF(CGM); 715 FunctionArgList Args; 716 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 717 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 718 Args.push_back(&Dst); 719 720 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 721 CGM.getContext().VoidPtrTy, Args, FunctionType::ExtInfo(), 722 /*isVariadic=*/false); 723 auto FTy = CGM.getTypes().GetFunctionType(FI); 724 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 725 FTy, ".__kmpc_global_ctor_.", Loc); 726 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 727 Args, SourceLocation()); 728 auto ArgVal = CtorCGF.EmitLoadOfScalar( 729 CtorCGF.GetAddrOfLocalVar(&Dst), 730 /*Volatile=*/false, CGM.PointerAlignInBytes, 731 CGM.getContext().VoidPtrTy, Dst.getLocation()); 732 auto Arg = CtorCGF.Builder.CreatePointerCast( 733 ArgVal, 734 CtorCGF.ConvertTypeForMem(CGM.getContext().getPointerType(ASTTy))); 735 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 736 /*IsInitializer=*/true); 737 ArgVal = CtorCGF.EmitLoadOfScalar( 738 CtorCGF.GetAddrOfLocalVar(&Dst), 739 /*Volatile=*/false, CGM.PointerAlignInBytes, 740 CGM.getContext().VoidPtrTy, Dst.getLocation()); 741 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 742 CtorCGF.FinishFunction(); 743 Ctor = Fn; 744 } 745 if (VD->getType().isDestructedType() != QualType::DK_none) { 746 // Generate function that emits destructor call for the threadprivate copy 747 // of the variable VD 748 CodeGenFunction DtorCGF(CGM); 749 FunctionArgList Args; 750 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, SourceLocation(), 751 /*Id=*/nullptr, CGM.getContext().VoidPtrTy); 752 Args.push_back(&Dst); 753 754 auto &FI = CGM.getTypes().arrangeFreeFunctionDeclaration( 755 CGM.getContext().VoidTy, Args, FunctionType::ExtInfo(), 756 /*isVariadic=*/false); 757 auto FTy = CGM.getTypes().GetFunctionType(FI); 758 auto Fn = CGM.CreateGlobalInitOrDestructFunction( 759 FTy, ".__kmpc_global_dtor_.", Loc); 760 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 761 SourceLocation()); 762 auto ArgVal = DtorCGF.EmitLoadOfScalar( 763 DtorCGF.GetAddrOfLocalVar(&Dst), 764 /*Volatile=*/false, CGM.PointerAlignInBytes, 765 CGM.getContext().VoidPtrTy, Dst.getLocation()); 766 DtorCGF.emitDestroy(ArgVal, ASTTy, 767 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 768 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 769 DtorCGF.FinishFunction(); 770 Dtor = Fn; 771 } 772 // Do not emit init function if it is not required. 773 if (!Ctor && !Dtor) 774 return nullptr; 775 776 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 777 auto CopyCtorTy = 778 llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 779 /*isVarArg=*/false)->getPointerTo(); 780 // Copying constructor for the threadprivate variable. 781 // Must be NULL - reserved by runtime, but currently it requires that this 782 // parameter is always NULL. Otherwise it fires assertion. 783 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 784 if (Ctor == nullptr) { 785 auto CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 786 /*isVarArg=*/false)->getPointerTo(); 787 Ctor = llvm::Constant::getNullValue(CtorTy); 788 } 789 if (Dtor == nullptr) { 790 auto DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 791 /*isVarArg=*/false)->getPointerTo(); 792 Dtor = llvm::Constant::getNullValue(DtorTy); 793 } 794 if (!CGF) { 795 auto InitFunctionTy = 796 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 797 auto InitFunction = CGM.CreateGlobalInitOrDestructFunction( 798 InitFunctionTy, ".__omp_threadprivate_init_."); 799 CodeGenFunction InitCGF(CGM); 800 FunctionArgList ArgList; 801 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 802 CGM.getTypes().arrangeNullaryFunction(), ArgList, 803 Loc); 804 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 805 InitCGF.FinishFunction(); 806 return InitFunction; 807 } 808 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 809 } 810 return nullptr; 811 } 812 813 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 814 llvm::Value *OutlinedFn, 815 llvm::Value *CapturedStruct) { 816 // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/) 817 llvm::Value *Args[] = { 818 emitUpdateLocation(CGF, Loc), 819 CGF.Builder.getInt32(1), // Number of arguments after 'microtask' argument 820 // (there is only one additional argument - 'context') 821 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy()), 822 CGF.EmitCastToVoidPtr(CapturedStruct)}; 823 auto RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_call); 824 CGF.EmitRuntimeCall(RTLFn, Args); 825 } 826 827 void CGOpenMPRuntime::emitSerialCall(CodeGenFunction &CGF, SourceLocation Loc, 828 llvm::Value *OutlinedFn, 829 llvm::Value *CapturedStruct) { 830 auto ThreadID = getThreadID(CGF, Loc); 831 // Build calls: 832 // __kmpc_serialized_parallel(&Loc, GTid); 833 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), ThreadID}; 834 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), 835 Args); 836 837 // OutlinedFn(>id, &zero, CapturedStruct); 838 auto ThreadIDAddr = emitThreadIDAddress(CGF, Loc); 839 auto Int32Ty = 840 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 841 auto ZeroAddr = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".zero.addr"); 842 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 843 llvm::Value *OutlinedFnArgs[] = {ThreadIDAddr, ZeroAddr, CapturedStruct}; 844 CGF.EmitCallOrInvoke(OutlinedFn, OutlinedFnArgs); 845 846 // __kmpc_end_serialized_parallel(&Loc, GTid); 847 llvm::Value *EndArgs[] = {emitUpdateLocation(CGF, Loc), ThreadID}; 848 CGF.EmitRuntimeCall( 849 createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), EndArgs); 850 } 851 852 // If we're inside an (outlined) parallel region, use the region info's 853 // thread-ID variable (it is passed in a first argument of the outlined function 854 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 855 // regular serial code region, get thread ID by calling kmp_int32 856 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 857 // return the address of that temp. 858 llvm::Value *CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 859 SourceLocation Loc) { 860 if (auto OMPRegionInfo = 861 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 862 if (OMPRegionInfo->getThreadIDVariable()) 863 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 864 865 auto ThreadID = getThreadID(CGF, Loc); 866 auto Int32Ty = 867 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 868 auto ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 869 CGF.EmitStoreOfScalar(ThreadID, 870 CGF.MakeNaturalAlignAddrLValue(ThreadIDTemp, Int32Ty)); 871 872 return ThreadIDTemp; 873 } 874 875 llvm::Constant * 876 CGOpenMPRuntime::getOrCreateInternalVariable(llvm::Type *Ty, 877 const llvm::Twine &Name) { 878 SmallString<256> Buffer; 879 llvm::raw_svector_ostream Out(Buffer); 880 Out << Name; 881 auto RuntimeName = Out.str(); 882 auto &Elem = *InternalVars.insert(std::make_pair(RuntimeName, nullptr)).first; 883 if (Elem.second) { 884 assert(Elem.second->getType()->getPointerElementType() == Ty && 885 "OMP internal variable has different type than requested"); 886 return &*Elem.second; 887 } 888 889 return Elem.second = new llvm::GlobalVariable( 890 CGM.getModule(), Ty, /*IsConstant*/ false, 891 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 892 Elem.first()); 893 } 894 895 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 896 llvm::Twine Name(".gomp_critical_user_", CriticalName); 897 return getOrCreateInternalVariable(KmpCriticalNameTy, Name.concat(".var")); 898 } 899 900 void CGOpenMPRuntime::emitCriticalRegion( 901 CodeGenFunction &CGF, StringRef CriticalName, 902 const std::function<void()> &CriticalOpGen, SourceLocation Loc) { 903 auto RegionLock = getCriticalRegionLock(CriticalName); 904 // __kmpc_critical(ident_t *, gtid, Lock); 905 // CriticalOpGen(); 906 // __kmpc_end_critical(ident_t *, gtid, Lock); 907 // Prepare arguments and build a call to __kmpc_critical 908 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 909 RegionLock}; 910 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_critical), Args); 911 CriticalOpGen(); 912 // Build a call to __kmpc_end_critical 913 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 914 } 915 916 static void emitIfStmt(CodeGenFunction &CGF, llvm::Value *IfCond, 917 const std::function<void()> &BodyOpGen) { 918 llvm::Value *CallBool = CGF.EmitScalarConversion( 919 IfCond, 920 CGF.getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true), 921 CGF.getContext().BoolTy); 922 923 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 924 auto *ContBlock = CGF.createBasicBlock("omp_if.end"); 925 // Generate the branch (If-stmt) 926 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 927 CGF.EmitBlock(ThenBlock); 928 BodyOpGen(); 929 // Emit the rest of bblocks/branches 930 CGF.EmitBranch(ContBlock); 931 CGF.EmitBlock(ContBlock, true); 932 } 933 934 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 935 const std::function<void()> &MasterOpGen, 936 SourceLocation Loc) { 937 // if(__kmpc_master(ident_t *, gtid)) { 938 // MasterOpGen(); 939 // __kmpc_end_master(ident_t *, gtid); 940 // } 941 // Prepare arguments and build a call to __kmpc_master 942 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 943 auto *IsMaster = 944 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_master), Args); 945 emitIfStmt(CGF, IsMaster, [&]() -> void { 946 MasterOpGen(); 947 // Build a call to __kmpc_end_master. 948 // OpenMP [1.2.2 OpenMP Language Terminology] 949 // For C/C++, an executable statement, possibly compound, with a single 950 // entry at the top and a single exit at the bottom, or an OpenMP construct. 951 // * Access to the structured block must not be the result of a branch. 952 // * The point of exit cannot be a branch out of the structured block. 953 // * The point of entry must not be a call to setjmp(). 954 // * longjmp() and throw() must not violate the entry/exit criteria. 955 // * An expression statement, iteration statement, selection statement, or 956 // try block is considered to be a structured block if the corresponding 957 // compound statement obtained by enclosing it in { and } would be a 958 // structured block. 959 // It is analyzed in Sema, so we can just call __kmpc_end_master() on 960 // fallthrough rather than pushing a normal cleanup for it. 961 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_master), Args); 962 }); 963 } 964 965 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 966 SourceLocation Loc) { 967 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 968 llvm::Value *Args[] = { 969 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 970 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 971 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 972 } 973 974 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 975 const std::function<void()> &SingleOpGen, 976 SourceLocation Loc) { 977 // if(__kmpc_single(ident_t *, gtid)) { 978 // SingleOpGen(); 979 // __kmpc_end_single(ident_t *, gtid); 980 // } 981 // Prepare arguments and build a call to __kmpc_single 982 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 983 auto *IsSingle = 984 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_single), Args); 985 emitIfStmt(CGF, IsSingle, [&]() -> void { 986 SingleOpGen(); 987 // Build a call to __kmpc_end_single. 988 // OpenMP [1.2.2 OpenMP Language Terminology] 989 // For C/C++, an executable statement, possibly compound, with a single 990 // entry at the top and a single exit at the bottom, or an OpenMP construct. 991 // * Access to the structured block must not be the result of a branch. 992 // * The point of exit cannot be a branch out of the structured block. 993 // * The point of entry must not be a call to setjmp(). 994 // * longjmp() and throw() must not violate the entry/exit criteria. 995 // * An expression statement, iteration statement, selection statement, or 996 // try block is considered to be a structured block if the corresponding 997 // compound statement obtained by enclosing it in { and } would be a 998 // structured block. 999 // It is analyzed in Sema, so we can just call __kmpc_end_single() on 1000 // fallthrough rather than pushing a normal cleanup for it. 1001 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_end_single), Args); 1002 }); 1003 } 1004 1005 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 1006 bool IsExplicit) { 1007 // Build call __kmpc_cancel_barrier(loc, thread_id); 1008 auto Flags = static_cast<OpenMPLocationFlags>( 1009 OMP_IDENT_KMPC | 1010 (IsExplicit ? OMP_IDENT_BARRIER_EXPL : OMP_IDENT_BARRIER_IMPL)); 1011 // Build call __kmpc_cancel_barrier(loc, thread_id); 1012 // Replace __kmpc_barrier() function by __kmpc_cancel_barrier() because this 1013 // one provides the same functionality and adds initial support for 1014 // cancellation constructs introduced in OpenMP 4.0. __kmpc_cancel_barrier() 1015 // is provided default by the runtime library so it safe to make such 1016 // replacement. 1017 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 1018 getThreadID(CGF, Loc)}; 1019 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 1020 } 1021 1022 /// \brief Schedule types for 'omp for' loops (these enumerators are taken from 1023 /// the enum sched_type in kmp.h). 1024 enum OpenMPSchedType { 1025 /// \brief Lower bound for default (unordered) versions. 1026 OMP_sch_lower = 32, 1027 OMP_sch_static_chunked = 33, 1028 OMP_sch_static = 34, 1029 OMP_sch_dynamic_chunked = 35, 1030 OMP_sch_guided_chunked = 36, 1031 OMP_sch_runtime = 37, 1032 OMP_sch_auto = 38, 1033 /// \brief Lower bound for 'ordered' versions. 1034 OMP_ord_lower = 64, 1035 /// \brief Lower bound for 'nomerge' versions. 1036 OMP_nm_lower = 160, 1037 }; 1038 1039 /// \brief Map the OpenMP loop schedule to the runtime enumeration. 1040 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 1041 bool Chunked) { 1042 switch (ScheduleKind) { 1043 case OMPC_SCHEDULE_static: 1044 return Chunked ? OMP_sch_static_chunked : OMP_sch_static; 1045 case OMPC_SCHEDULE_dynamic: 1046 return OMP_sch_dynamic_chunked; 1047 case OMPC_SCHEDULE_guided: 1048 return OMP_sch_guided_chunked; 1049 case OMPC_SCHEDULE_auto: 1050 return OMP_sch_auto; 1051 case OMPC_SCHEDULE_runtime: 1052 return OMP_sch_runtime; 1053 case OMPC_SCHEDULE_unknown: 1054 assert(!Chunked && "chunk was specified but schedule kind not known"); 1055 return OMP_sch_static; 1056 } 1057 llvm_unreachable("Unexpected runtime schedule"); 1058 } 1059 1060 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 1061 bool Chunked) const { 1062 auto Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 1063 return Schedule == OMP_sch_static; 1064 } 1065 1066 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 1067 auto Schedule = getRuntimeSchedule(ScheduleKind, /* Chunked */ false); 1068 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 1069 return Schedule != OMP_sch_static; 1070 } 1071 1072 void CGOpenMPRuntime::emitForInit(CodeGenFunction &CGF, SourceLocation Loc, 1073 OpenMPScheduleClauseKind ScheduleKind, 1074 unsigned IVSize, bool IVSigned, 1075 llvm::Value *IL, llvm::Value *LB, 1076 llvm::Value *UB, llvm::Value *ST, 1077 llvm::Value *Chunk) { 1078 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunk != nullptr); 1079 // Call __kmpc_for_static_init( 1080 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 1081 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 1082 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 1083 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 1084 // TODO: Implement dynamic schedule. 1085 1086 // If the Chunk was not specified in the clause - use default value 1. 1087 if (Chunk == nullptr) 1088 Chunk = CGF.Builder.getIntN(IVSize, /*C*/ 1); 1089 1090 llvm::Value *Args[] = { 1091 emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), getThreadID(CGF, Loc), 1092 CGF.Builder.getInt32(Schedule), // Schedule type 1093 IL, // &isLastIter 1094 LB, // &LB 1095 UB, // &UB 1096 ST, // &Stride 1097 CGF.Builder.getIntN(IVSize, 1), // Incr 1098 Chunk // Chunk 1099 }; 1100 assert((IVSize == 32 || IVSize == 64) && 1101 "Index size is not compatible with the omp runtime"); 1102 auto F = IVSize == 32 ? (IVSigned ? OMPRTL__kmpc_for_static_init_4 1103 : OMPRTL__kmpc_for_static_init_4u) 1104 : (IVSigned ? OMPRTL__kmpc_for_static_init_8 1105 : OMPRTL__kmpc_for_static_init_8u); 1106 CGF.EmitRuntimeCall(createRuntimeFunction(F), Args); 1107 } 1108 1109 void CGOpenMPRuntime::emitForFinish(CodeGenFunction &CGF, SourceLocation Loc, 1110 OpenMPScheduleClauseKind ScheduleKind) { 1111 assert((ScheduleKind == OMPC_SCHEDULE_static || 1112 ScheduleKind == OMPC_SCHEDULE_unknown) && 1113 "Non-static schedule kinds are not yet implemented"); 1114 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 1115 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, OMP_IDENT_KMPC), 1116 getThreadID(CGF, Loc)}; 1117 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 1118 Args); 1119 } 1120 1121 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 1122 llvm::Value *NumThreads, 1123 SourceLocation Loc) { 1124 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 1125 llvm::Value *Args[] = { 1126 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1127 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 1128 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 1129 Args); 1130 } 1131 1132 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 1133 SourceLocation Loc) { 1134 // Build call void __kmpc_flush(ident_t *loc) 1135 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 1136 emitUpdateLocation(CGF, Loc)); 1137 } 1138 1139 namespace { 1140 /// \brief Indexes of fields for type kmp_task_t. 1141 enum KmpTaskTFields { 1142 /// \brief List of shared variables. 1143 KmpTaskTShareds, 1144 /// \brief Task routine. 1145 KmpTaskTRoutine, 1146 /// \brief Partition id for the untied tasks. 1147 KmpTaskTPartId, 1148 /// \brief Function with call of destructors for private variables. 1149 KmpTaskTDestructors, 1150 }; 1151 } // namespace 1152 1153 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 1154 if (!KmpRoutineEntryPtrTy) { 1155 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 1156 auto &C = CGM.getContext(); 1157 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 1158 FunctionProtoType::ExtProtoInfo EPI; 1159 KmpRoutineEntryPtrQTy = C.getPointerType( 1160 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 1161 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 1162 } 1163 } 1164 1165 static void addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1166 QualType FieldTy) { 1167 auto *Field = FieldDecl::Create( 1168 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1169 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1170 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1171 Field->setAccess(AS_public); 1172 DC->addDecl(Field); 1173 } 1174 1175 static QualType createKmpTaskTRecordDecl(CodeGenModule &CGM, 1176 QualType KmpInt32Ty, 1177 QualType KmpRoutineEntryPointerQTy) { 1178 auto &C = CGM.getContext(); 1179 // Build struct kmp_task_t { 1180 // void * shareds; 1181 // kmp_routine_entry_t routine; 1182 // kmp_int32 part_id; 1183 // kmp_routine_entry_t destructors; 1184 // /* private vars */ 1185 // }; 1186 auto *RD = C.buildImplicitRecord("kmp_task_t"); 1187 RD->startDefinition(); 1188 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1189 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 1190 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1191 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 1192 // TODO: add private fields. 1193 RD->completeDefinition(); 1194 return C.getRecordType(RD); 1195 } 1196 1197 /// \brief Emit a proxy function which accepts kmp_task_t as the second 1198 /// argument. 1199 /// \code 1200 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 1201 /// TaskFunction(gtid, tt->part_id, tt->shareds); 1202 /// return 0; 1203 /// } 1204 /// \endcode 1205 static llvm::Value * 1206 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 1207 QualType KmpInt32Ty, QualType KmpTaskTPtrQTy, 1208 QualType SharedsPtrTy, llvm::Value *TaskFunction) { 1209 auto &C = CGM.getContext(); 1210 FunctionArgList Args; 1211 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty); 1212 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, 1213 /*Id=*/nullptr, KmpTaskTPtrQTy); 1214 Args.push_back(&GtidArg); 1215 Args.push_back(&TaskTypeArg); 1216 FunctionType::ExtInfo Info; 1217 auto &TaskEntryFnInfo = 1218 CGM.getTypes().arrangeFreeFunctionDeclaration(KmpInt32Ty, Args, Info, 1219 /*isVariadic=*/false); 1220 auto *TaskEntryTy = CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 1221 auto *TaskEntry = 1222 llvm::Function::Create(TaskEntryTy, llvm::GlobalValue::InternalLinkage, 1223 ".omp_task_entry.", &CGM.getModule()); 1224 CGM.SetLLVMFunctionAttributes(/*D=*/nullptr, TaskEntryFnInfo, TaskEntry); 1225 CodeGenFunction CGF(CGM); 1226 CGF.disableDebugInfo(); 1227 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args); 1228 1229 // TaskFunction(gtid, tt->part_id, tt->shareds); 1230 auto *GtidParam = CGF.EmitLoadOfScalar( 1231 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, 1232 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc); 1233 auto TaskTypeArgAddr = CGF.EmitLoadOfScalar( 1234 CGF.GetAddrOfLocalVar(&TaskTypeArg), /*Volatile=*/false, 1235 CGM.PointerAlignInBytes, KmpTaskTPtrQTy, Loc); 1236 auto *PartidPtr = CGF.Builder.CreateStructGEP(TaskTypeArgAddr, 1237 /*Idx=*/KmpTaskTPartId); 1238 auto *PartidParam = CGF.EmitLoadOfScalar( 1239 PartidPtr, /*Volatile=*/false, 1240 C.getTypeAlignInChars(KmpInt32Ty).getQuantity(), KmpInt32Ty, Loc); 1241 auto *SharedsPtr = CGF.Builder.CreateStructGEP(TaskTypeArgAddr, 1242 /*Idx=*/KmpTaskTShareds); 1243 auto *SharedsParam = 1244 CGF.EmitLoadOfScalar(SharedsPtr, /*Volatile=*/false, 1245 CGM.PointerAlignInBytes, C.VoidPtrTy, Loc); 1246 llvm::Value *CallArgs[] = { 1247 GtidParam, PartidParam, 1248 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1249 SharedsParam, CGF.ConvertTypeForMem(SharedsPtrTy))}; 1250 CGF.EmitCallOrInvoke(TaskFunction, CallArgs); 1251 CGF.EmitStoreThroughLValue( 1252 RValue::get(CGF.Builder.getInt32(/*C=*/0)), 1253 CGF.MakeNaturalAlignAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 1254 CGF.FinishFunction(); 1255 return TaskEntry; 1256 } 1257 1258 void CGOpenMPRuntime::emitTaskCall( 1259 CodeGenFunction &CGF, SourceLocation Loc, bool Tied, 1260 llvm::PointerIntPair<llvm::Value *, 1, bool> Final, 1261 llvm::Value *TaskFunction, QualType SharedsTy, llvm::Value *Shareds) { 1262 auto &C = CGM.getContext(); 1263 auto KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1264 // Build type kmp_routine_entry_t (if not built yet). 1265 emitKmpRoutineEntryT(KmpInt32Ty); 1266 // Build particular struct kmp_task_t for the given task. 1267 auto KmpTaskQTy = 1268 createKmpTaskTRecordDecl(CGM, KmpInt32Ty, KmpRoutineEntryPtrQTy); 1269 QualType KmpTaskTPtrQTy = C.getPointerType(KmpTaskQTy); 1270 auto KmpTaskTPtrTy = CGF.ConvertType(KmpTaskQTy)->getPointerTo(); 1271 auto KmpTaskTySize = CGM.getSize(C.getTypeSizeInChars(KmpTaskQTy)); 1272 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 1273 1274 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 1275 // kmp_task_t *tt); 1276 auto *TaskEntry = emitProxyTaskFunction(CGM, Loc, KmpInt32Ty, KmpTaskTPtrQTy, 1277 SharedsPtrTy, TaskFunction); 1278 1279 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1280 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1281 // kmp_routine_entry_t *task_entry); 1282 // Task flags. Format is taken from 1283 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp.h, 1284 // description of kmp_tasking_flags struct. 1285 const unsigned TiedFlag = 0x1; 1286 const unsigned FinalFlag = 0x2; 1287 unsigned Flags = Tied ? TiedFlag : 0; 1288 auto *TaskFlags = 1289 Final.getPointer() 1290 ? CGF.Builder.CreateSelect(Final.getPointer(), 1291 CGF.Builder.getInt32(FinalFlag), 1292 CGF.Builder.getInt32(/*C=*/0)) 1293 : CGF.Builder.getInt32(Final.getInt() ? FinalFlag : 0); 1294 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 1295 auto SharedsSize = C.getTypeSizeInChars(SharedsTy); 1296 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc), 1297 getThreadID(CGF, Loc), TaskFlags, KmpTaskTySize, 1298 CGM.getSize(SharedsSize), 1299 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1300 TaskEntry, KmpRoutineEntryPtrTy)}; 1301 auto *NewTask = CGF.EmitRuntimeCall( 1302 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 1303 auto *NewTaskNewTaskTTy = 1304 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(NewTask, KmpTaskTPtrTy); 1305 // Fill the data in the resulting kmp_task_t record. 1306 // Copy shareds if there are any. 1307 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) 1308 CGF.EmitAggregateCopy( 1309 CGF.EmitLoadOfScalar( 1310 CGF.Builder.CreateStructGEP(NewTaskNewTaskTTy, 1311 /*Idx=*/KmpTaskTShareds), 1312 /*Volatile=*/false, CGM.PointerAlignInBytes, SharedsPtrTy, Loc), 1313 Shareds, SharedsTy); 1314 // TODO: generate function with destructors for privates. 1315 // Provide pointer to function with destructors for privates. 1316 CGF.Builder.CreateAlignedStore( 1317 llvm::ConstantPointerNull::get( 1318 cast<llvm::PointerType>(KmpRoutineEntryPtrTy)), 1319 CGF.Builder.CreateStructGEP(NewTaskNewTaskTTy, 1320 /*Idx=*/KmpTaskTDestructors), 1321 CGM.PointerAlignInBytes); 1322 1323 // NOTE: routine and part_id fields are intialized by __kmpc_omp_task_alloc() 1324 // libcall. 1325 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1326 // *new_task); 1327 llvm::Value *TaskArgs[] = {emitUpdateLocation(CGF, Loc), 1328 getThreadID(CGF, Loc), NewTask}; 1329 // TODO: add check for untied tasks. 1330 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1331 } 1332 1333 InlinedOpenMPRegionRAII::InlinedOpenMPRegionRAII( 1334 CodeGenFunction &CGF, const OMPExecutableDirective &D) 1335 : CGF(CGF) { 1336 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(D, CGF.CapturedStmtInfo); 1337 // 1.2.2 OpenMP Language Terminology 1338 // Structured block - An executable statement with a single entry at the 1339 // top and a single exit at the bottom. 1340 // The point of exit cannot be a branch out of the structured block. 1341 // longjmp() and throw() must not violate the entry/exit criteria. 1342 CGF.EHStack.pushTerminate(); 1343 } 1344 1345 InlinedOpenMPRegionRAII::~InlinedOpenMPRegionRAII() { 1346 CGF.EHStack.popTerminate(); 1347 auto *OldCSI = 1348 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 1349 delete CGF.CapturedStmtInfo; 1350 CGF.CapturedStmtInfo = OldCSI; 1351 } 1352 1353