Home | History | Annotate | Download | only in CodeGen
      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     // 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 
    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 
    150 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
    151   return llvm::PointerType::getUnqual(IdentTy);
    152 }
    153 
    154 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
    155   return llvm::PointerType::getUnqual(Kmpc_MicroTy);
    156 }
    157 
    158 llvm::Constant *
    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