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 "clang/AST/Decl.h" 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/GlobalValue.h" 20 #include "llvm/IR/Value.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <cassert> 23 24 using namespace clang; 25 using namespace CodeGen; 26 27 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM) 28 : CGM(CGM), DefaultOpenMPPSource(nullptr) { 29 IdentTy = llvm::StructType::create( 30 "ident_t", CGM.Int32Ty /* reserved_1 */, CGM.Int32Ty /* flags */, 31 CGM.Int32Ty /* reserved_2 */, CGM.Int32Ty /* reserved_3 */, 32 CGM.Int8PtrTy /* psource */, NULL); 33 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 34 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 35 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 36 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 37 } 38 39 llvm::Value * 40 CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) { 41 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(Flags); 42 if (!Entry) { 43 if (!DefaultOpenMPPSource) { 44 // Initialize default location for psource field of ident_t structure of 45 // all ident_t objects. Format is ";file;function;line;column;;". 46 // Taken from 47 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c 48 DefaultOpenMPPSource = 49 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;"); 50 DefaultOpenMPPSource = 51 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 52 } 53 llvm::GlobalVariable *DefaultOpenMPLocation = cast<llvm::GlobalVariable>( 54 CGM.CreateRuntimeVariable(IdentTy, ".kmpc_default_loc.addr")); 55 DefaultOpenMPLocation->setUnnamedAddr(true); 56 DefaultOpenMPLocation->setConstant(true); 57 DefaultOpenMPLocation->setLinkage(llvm::GlobalValue::PrivateLinkage); 58 59 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true); 60 llvm::Constant *Values[] = {Zero, 61 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 62 Zero, Zero, DefaultOpenMPPSource}; 63 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 64 DefaultOpenMPLocation->setInitializer(Init); 65 return DefaultOpenMPLocation; 66 } 67 return Entry; 68 } 69 70 llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation( 71 CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) { 72 // If no debug info is generated - return global default location. 73 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo || 74 Loc.isInvalid()) 75 return GetOrCreateDefaultOpenMPLocation(Flags); 76 77 assert(CGF.CurFn && "No function in current CodeGenFunction."); 78 79 llvm::Value *LocValue = nullptr; 80 OpenMPLocMapTy::iterator I = OpenMPLocMap.find(CGF.CurFn); 81 if (I != OpenMPLocMap.end()) { 82 LocValue = I->second; 83 } else { 84 // Generate "ident_t .kmpc_loc.addr;" 85 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr"); 86 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy)); 87 OpenMPLocMap[CGF.CurFn] = AI; 88 LocValue = AI; 89 90 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 91 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 92 CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags), 93 llvm::ConstantExpr::getSizeOf(IdentTy), 94 CGM.PointerAlignInBytes); 95 } 96 97 // char **psource = &.kmpc_loc_<flags>.addr.psource; 98 llvm::Value *PSource = 99 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource); 100 101 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 102 if (OMPDebugLoc == nullptr) { 103 SmallString<128> Buffer2; 104 llvm::raw_svector_ostream OS2(Buffer2); 105 // Build debug location 106 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 107 OS2 << ";" << PLoc.getFilename() << ";"; 108 if (const FunctionDecl *FD = 109 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 110 OS2 << FD->getQualifiedNameAsString(); 111 } 112 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 113 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 114 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 115 } 116 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 117 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 118 119 return LocValue; 120 } 121 122 llvm::Value *CGOpenMPRuntime::GetOpenMPGlobalThreadNum(CodeGenFunction &CGF, 123 SourceLocation Loc) { 124 assert(CGF.CurFn && "No function in current CodeGenFunction."); 125 126 llvm::Value *GTid = nullptr; 127 OpenMPGtidMapTy::iterator I = OpenMPGtidMap.find(CGF.CurFn); 128 if (I != OpenMPGtidMap.end()) { 129 GTid = I->second; 130 } else { 131 // Check if current function is a function which has first parameter 132 // with type int32 and name ".global_tid.". 133 if (!CGF.CurFn->arg_empty() && 134 CGF.CurFn->arg_begin()->getType()->isPointerTy() && 135 CGF.CurFn->arg_begin() 136 ->getType() 137 ->getPointerElementType() 138 ->isIntegerTy() && 139 CGF.CurFn->arg_begin() 140 ->getType() 141 ->getPointerElementType() 142 ->getIntegerBitWidth() == 32 && 143 CGF.CurFn->arg_begin()->hasName() && 144 CGF.CurFn->arg_begin()->getName() == ".global_tid.") { 145 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 146 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 147 GTid = CGF.Builder.CreateLoad(CGF.CurFn->arg_begin()); 148 } else { 149 // Generate "int32 .kmpc_global_thread_num.addr;" 150 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 151 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 152 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)}; 153 GTid = CGF.EmitRuntimeCall( 154 CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args); 155 } 156 OpenMPGtidMap[CGF.CurFn] = GTid; 157 } 158 return GTid; 159 } 160 161 void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) { 162 assert(CGF.CurFn && "No function in current CodeGenFunction."); 163 if (OpenMPGtidMap.count(CGF.CurFn)) 164 OpenMPGtidMap.erase(CGF.CurFn); 165 if (OpenMPLocMap.count(CGF.CurFn)) 166 OpenMPLocMap.erase(CGF.CurFn); 167 } 168 169 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 170 return llvm::PointerType::getUnqual(IdentTy); 171 } 172 173 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 174 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 175 } 176 177 llvm::Constant * 178 CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { 179 llvm::Constant *RTLFn = nullptr; 180 switch (Function) { 181 case OMPRTL__kmpc_fork_call: { 182 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 183 // microtask, ...); 184 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 185 getKmpc_MicroPointerTy()}; 186 llvm::FunctionType *FnTy = 187 llvm::FunctionType::get(CGM.VoidTy, TypeParams, true); 188 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 189 break; 190 } 191 case OMPRTL__kmpc_global_thread_num: { 192 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 193 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 194 llvm::FunctionType *FnTy = 195 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false); 196 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 197 break; 198 } 199 } 200 return RTLFn; 201 } 202