1//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
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 contains code to emit OpenMP nodes as LLVM code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
17#include "clang/AST/Stmt.h"
18#include "clang/AST/StmtOpenMP.h"
19using namespace clang;
20using namespace CodeGen;
21
22//===----------------------------------------------------------------------===//
23//                              OpenMP Directive Emission
24//===----------------------------------------------------------------------===//
25
26void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
27  const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
28  llvm::Value *CapturedStruct = GenerateCapturedStmtArgument(*CS);
29
30  llvm::Value *OutlinedFn;
31  {
32    CodeGenFunction CGF(CGM, true);
33    CGCapturedStmtInfo CGInfo(*CS, CS->getCapturedRegionKind());
34    CGF.CapturedStmtInfo = &CGInfo;
35    OutlinedFn = CGF.GenerateCapturedStmtFunction(*CS);
36  }
37
38  // Build call __kmpc_fork_call(loc, 1, microtask, captured_struct/*context*/)
39  llvm::Value *Args[] = {
40      CGM.getOpenMPRuntime().EmitOpenMPUpdateLocation(*this, S.getLocStart()),
41      Builder.getInt32(1), // Number of arguments after 'microtask' argument
42      // (there is only one additional argument - 'context')
43      Builder.CreateBitCast(OutlinedFn,
44                            CGM.getOpenMPRuntime().getKmpc_MicroPointerTy()),
45      EmitCastToVoidPtr(CapturedStruct)};
46  llvm::Constant *RTLFn = CGM.getOpenMPRuntime().CreateRuntimeFunction(
47      CGOpenMPRuntime::OMPRTL__kmpc_fork_call);
48  EmitRuntimeCall(RTLFn, Args);
49}
50
51void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
52  const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
53  const Stmt *Body = CS->getCapturedStmt();
54  LoopStack.setParallel();
55  LoopStack.setVectorizerEnable(true);
56  for (auto C : S.clauses()) {
57    switch (C->getClauseKind()) {
58    case OMPC_safelen: {
59      RValue Len = EmitAnyExpr(cast<OMPSafelenClause>(C)->getSafelen(),
60                               AggValueSlot::ignored(), true);
61      llvm::ConstantInt *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
62      LoopStack.setVectorizerWidth(Val->getZExtValue());
63      // In presence of finite 'safelen', it may be unsafe to mark all
64      // the memory instructions parallel, because loop-carried
65      // dependences of 'safelen' iterations are possible.
66      LoopStack.setParallel(false);
67      break;
68    }
69    default:
70      // Not handled yet
71      ;
72    }
73  }
74  EmitStmt(Body);
75}
76
77void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &) {
78  llvm_unreachable("CodeGen for 'omp for' is not supported yet.");
79}
80
81void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &) {
82  llvm_unreachable("CodeGen for 'omp sections' is not supported yet.");
83}
84
85void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &) {
86  llvm_unreachable("CodeGen for 'omp section' is not supported yet.");
87}
88
89void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) {
90  llvm_unreachable("CodeGen for 'omp single' is not supported yet.");
91}
92
93void
94CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) {
95  llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet.");
96}
97
98void CodeGenFunction::EmitOMPParallelSectionsDirective(
99    const OMPParallelSectionsDirective &) {
100  llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet.");
101}
102
103