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
CGOpenMPRuntime(CodeGenModule & CGM)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 *
GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags)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
EmitOpenMPUpdateLocation(CodeGenFunction & CGF,SourceLocation Loc,OpenMPLocationFlags Flags)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
GetOpenMPGlobalThreadNum(CodeGenFunction & CGF,SourceLocation Loc)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 // Generate "int32 .kmpc_global_thread_num.addr;"
132 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
133 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
134 llvm::Value *Args[] = {EmitOpenMPUpdateLocation(CGF, Loc)};
135 GTid = CGF.EmitRuntimeCall(
136 CreateRuntimeFunction(OMPRTL__kmpc_global_thread_num), Args);
137 OpenMPGtidMap[CGF.CurFn] = GTid;
138 }
139 return GTid;
140 }
141
FunctionFinished(CodeGenFunction & CGF)142 void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) {
143 assert(CGF.CurFn && "No function in current CodeGenFunction.");
144 if (OpenMPGtidMap.count(CGF.CurFn))
145 OpenMPGtidMap.erase(CGF.CurFn);
146 if (OpenMPLocMap.count(CGF.CurFn))
147 OpenMPLocMap.erase(CGF.CurFn);
148 }
149
getIdentTyPointerTy()150 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
151 return llvm::PointerType::getUnqual(IdentTy);
152 }
153
getKmpc_MicroPointerTy()154 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
155 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
156 }
157
158 llvm::Constant *
CreateRuntimeFunction(OpenMPRTLFunction Function)159 CGOpenMPRuntime::CreateRuntimeFunction(OpenMPRTLFunction Function) {
160 llvm::Constant *RTLFn = nullptr;
161 switch (Function) {
162 case OMPRTL__kmpc_fork_call: {
163 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
164 // microtask, ...);
165 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
166 getKmpc_MicroPointerTy()};
167 llvm::FunctionType *FnTy =
168 llvm::FunctionType::get(CGM.VoidTy, TypeParams, true);
169 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
170 break;
171 }
172 case OMPRTL__kmpc_global_thread_num: {
173 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
174 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
175 llvm::FunctionType *FnTy =
176 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, false);
177 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
178 break;
179 }
180 }
181 return RTLFn;
182 }
183