blob: 2009f4091187408cfda2169d1e1c19e0b45f1526 [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- 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
24using namespace clang;
25using namespace CodeGen;
26
27CGOpenMPRuntime::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
39llvm::Value *
40CGOpenMPRuntime::GetOrCreateDefaultOpenMPLocation(OpenMPLocationFlags Flags) {
41 llvm::Twine OpenMPDefaultLocName =
42 ".kmpc_default_loc_" + llvm::Twine::utohexstr(Flags) + ".addr";
43 llvm::Value *Entry =
44 CGM.getModule().getNamedValue(OpenMPDefaultLocName.str());
45 if (!Entry) {
46 if (!DefaultOpenMPPSource) {
47 // Initialize default location for psource field of ident_t structure of
48 // all ident_t objects. Format is ";file;function;line;column;;".
49 // Taken from
50 // http://llvm.org/svn/llvm-project/openmp/trunk/runtime/src/kmp_str.c
51 DefaultOpenMPPSource =
52 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;");
53 DefaultOpenMPPSource =
54 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
55 }
56 llvm::GlobalVariable *DefaultOpenMPLocation = cast<llvm::GlobalVariable>(
57 CGM.CreateRuntimeVariable(IdentTy, OpenMPDefaultLocName.str()));
58 DefaultOpenMPLocation->setUnnamedAddr(true);
59 DefaultOpenMPLocation->setConstant(true);
60 DefaultOpenMPLocation->setLinkage(llvm::GlobalValue::PrivateLinkage);
61
62 llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
63 llvm::Constant *Values[] = { Zero,
64 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
65 Zero, Zero, DefaultOpenMPPSource };
66 llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
67 DefaultOpenMPLocation->setInitializer(Init);
68 return DefaultOpenMPLocation;
69 }
70 return Entry;
71}
72
73llvm::Value *CGOpenMPRuntime::EmitOpenMPUpdateLocation(
74 CodeGenFunction &CGF, SourceLocation Loc, OpenMPLocationFlags Flags) {
75 // If no debug info is generated - return global default location.
76 if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::NoDebugInfo ||
77 Loc.isInvalid())
78 return GetOrCreateDefaultOpenMPLocation(Flags);
79
80 assert(CGF.CurFn && "No function in current CodeGenFunction.");
81
82 llvm::Twine OpenMPLocName =
83 ".kmpc_loc_" + llvm::Twine::utohexstr(Flags) + ".addr";
84
85 llvm::Value *LocValue = nullptr;
86 OpenMPLocMapTy::iterator I = OpenMPLocMap.find(CGF.CurFn);
87 if (I != OpenMPLocMap.end()) {
88 LocValue = I->second;
89 } else {
90 // Generate "ident_t .kmpc_loc_<flags>.addr;"
91 llvm::AllocaInst *AI = CGF.CreateTempAlloca(IdentTy, OpenMPLocName);
92 AI->setAlignment(CGM.getDataLayout().getPrefTypeAlignment(IdentTy));
93 OpenMPLocMap[CGF.CurFn] = AI;
94 LocValue = AI;
95
96 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
97 CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt);
98 CGF.Builder.CreateMemCpy(LocValue, GetOrCreateDefaultOpenMPLocation(Flags),
99 llvm::ConstantExpr::getSizeOf(IdentTy),
100 CGM.PointerAlignInBytes);
101 }
102
103 // char **psource = &.kmpc_loc_<flags>.addr.psource;
104 llvm::Value *PSource =
105 CGF.Builder.CreateConstInBoundsGEP2_32(LocValue, 0, IdentField_PSource);
106
107 SmallString<128> Buffer2;
108 llvm::raw_svector_ostream OS2(Buffer2);
109 // Build debug location
110 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
111 OS2 << ";" << PLoc.getFilename() << ";";
112 if (const FunctionDecl *FD =
113 dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) {
114 OS2 << FD->getQualifiedNameAsString();
115 }
116 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
117 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
118 CGF.Builder.CreateStore(CGF.Builder.CreateGlobalStringPtr(OS2.str()),
119 PSource);
120 return LocValue;
121}
122
123llvm::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
143void 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
151llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
152 return llvm::PointerType::getUnqual(IdentTy);
153}
154
155llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
156 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
157}
158
159llvm::Constant *
160CGOpenMPRuntime::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}