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 <assert.h> 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[] = { 61 Zero, llvm::ConstantInt::get(CGM.Int32Ty, Flags), Zero, 62 Zero, DefaultOpenMPPSource 63 }; 64 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values); 65 DefaultOpenMPLocation->setInitializer(Init); 66 return DefaultOpenMPLocation; 67 } 68 return Entry; 69 } 70 71 llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation( 72 CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) { 73 // If no debug info is generated - return global default location. 74 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo || 75 Loc.isInvalid()) 76 return GetOrCreateDefaultOpenMPLocation(Flags); 77 78 assert(CGF.CurFn && "No function in current CodeGenFunction."); 79 80 llvm::Value *LocValue = nullptr; 81 OpenMPLocMapTy::iterator I = OpenMPLocMap.find(CGF.CurFn); 82 if (I != OpenMPLocMap.end()) { 83 LocValue = I->second; 84 } else { 85 // Generate "ident_t .kmpc_loc.addr;" 86 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, ".kmpc_loc.addr"); 87 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy)); 88 OpenMPLocMap[CGF.CurFn] = AI; 89 LocValue = AI; 90 91 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 92 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 93 CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags), 94 llvm::ConstantExpr::getSizeOf(IdentTy), 95 CGM.PointerAlignInBytes); 96 } 97 98 // char **psource = &.kmpc_loc_<flags>.addr.psource; 99 llvm::Value *PSource = 100 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource); 101 102 auto OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 103 if (OMPDebugLoc == nullptr) { 104 SmallString<128> Buffer2; 105 llvm::raw_svector_ostream OS2(Buffer2); 106 // Build debug location 107 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 108 OS2 << ";" << PLoc.getFilename() << ";"; 109 if (const FunctionDecl *FD = 110 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) { 111 OS2 << FD->getQualifiedNameAsString(); 112 } 113 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 114 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 115 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 116 } 117 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 118 CGF.Builder.CreateStore(OMPDebugLoc, PSource); 119 120 return LocValue; 121 } 122 123 llvm::Value *CGOpenMPRuntime::GetOpenMPGlobalThreadNum(CodeGenFunction &CGF, 124 SourceLocation Loc) { 125 assert(CGF.CurFn && "No function in current CodeGenFunction."); 126 127 llvm::Value *GTid = nullptr; 128 OpenMPGtidMapTy::iterator I = OpenMPGtidMap.find(CGF.CurFn); 129 if (I != OpenMPGtidMap.end()) { 130 GTid = I->second; 131 } else { 132 // Generate "int32 .kmpc_global_thread_num.addr;" 133 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 134 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); 135 llvm::Value *Args[] = { EmitOpenMPUpdateLocation(CGF, Loc) }; 136 GTid = CGF.EmitRuntimeCall( 137 CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args); 138 OpenMPGtidMap[CGF.CurFn] = GTid; 139 } 140 return GTid; 141 } 142 143 void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) { 144 assert(CGF.CurFn && "No function in current CodeGenFunction."); 145 if (OpenMPGtidMap.count(CGF.CurFn)) 146 OpenMPGtidMap.erase(CGF.CurFn); 147 if (OpenMPLocMap.count(CGF.CurFn)) 148 OpenMPLocMap.erase(CGF.CurFn); 149 } 150 151 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 152 return llvm::PointerType::getUnqual(IdentTy); 153 } 154 155 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 156 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 157 } 158 159 llvm::Constant * 160 CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) { 161 llvm::Constant *RTLFn = nullptr; 162 switch (Function) { 163 case OMPRTL__kmpc_fork_call: { 164 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 165 // microtask, ...); 166 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), CGM.Int32Ty, 167 getKmpc_MicroPointerTy() }; 168 llvm::FunctionType *FnTy = 169 llvm::FunctionType::get(CGM.VoidTy, TypeParams, true); 170 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 171 break; 172 } 173 case OMPRTL__kmpc_global_thread_num: { 174 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 175 llvm::Type *TypeParams[] = { getIdentTyPointerTy() }; 176 llvm::FunctionType *FnTy = 177 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false); 178 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 179 break; 180 } 181 } 182 return RTLFn; 183 } 184