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