xref: /llvm-project/flang/lib/Lower/OpenMP/ClauseProcessor.cpp (revision 662133a278f4f3553f061f7999759bae4e842820)
14d4af15cSKareem Ergawy //===-- ClauseProcessor.cpp -------------------------------------*- C++ -*-===//
24d4af15cSKareem Ergawy //
34d4af15cSKareem Ergawy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44d4af15cSKareem Ergawy // See https://llvm.org/LICENSE.txt for license information.
54d4af15cSKareem Ergawy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64d4af15cSKareem Ergawy //
74d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
84d4af15cSKareem Ergawy //
94d4af15cSKareem Ergawy // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
104d4af15cSKareem Ergawy //
114d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
124d4af15cSKareem Ergawy 
134d4af15cSKareem Ergawy #include "ClauseProcessor.h"
14f9e55796SKrzysztof Parzyszek #include "Clauses.h"
154d4af15cSKareem Ergawy 
164d4af15cSKareem Ergawy #include "flang/Lower/PFTBuilder.h"
174d4af15cSKareem Ergawy #include "flang/Parser/tools.h"
184d4af15cSKareem Ergawy #include "flang/Semantics/tools.h"
197ffeaf0eSharishch4 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
204d4af15cSKareem Ergawy 
214d4af15cSKareem Ergawy namespace Fortran {
224d4af15cSKareem Ergawy namespace lower {
234d4af15cSKareem Ergawy namespace omp {
244d4af15cSKareem Ergawy 
254d4af15cSKareem Ergawy /// Check for unsupported map operand types.
264d4af15cSKareem Ergawy static void checkMapType(mlir::Location location, mlir::Type type) {
27fac349a1SChristian Sigg   if (auto refType = mlir::dyn_cast<fir::ReferenceType>(type))
284d4af15cSKareem Ergawy     type = refType.getElementType();
29fac349a1SChristian Sigg   if (auto boxType = mlir::dyn_cast_or_null<fir::BoxType>(type))
30fac349a1SChristian Sigg     if (!mlir::isa<fir::PointerType>(boxType.getElementType()))
314d4af15cSKareem Ergawy       TODO(location, "OMPD_target_data MapOperand BoxType");
324d4af15cSKareem Ergawy }
334d4af15cSKareem Ergawy 
344d4af15cSKareem Ergawy static mlir::omp::ScheduleModifier
35148a5579SKrzysztof Parzyszek translateScheduleModifier(const omp::clause::Schedule::OrderingModifier &m) {
36f9e55796SKrzysztof Parzyszek   switch (m) {
37148a5579SKrzysztof Parzyszek   case omp::clause::Schedule::OrderingModifier::Monotonic:
384d4af15cSKareem Ergawy     return mlir::omp::ScheduleModifier::monotonic;
39148a5579SKrzysztof Parzyszek   case omp::clause::Schedule::OrderingModifier::Nonmonotonic:
404d4af15cSKareem Ergawy     return mlir::omp::ScheduleModifier::nonmonotonic;
414d4af15cSKareem Ergawy   }
424d4af15cSKareem Ergawy   return mlir::omp::ScheduleModifier::none;
434d4af15cSKareem Ergawy }
444d4af15cSKareem Ergawy 
454d4af15cSKareem Ergawy static mlir::omp::ScheduleModifier
46f9e55796SKrzysztof Parzyszek getScheduleModifier(const omp::clause::Schedule &clause) {
47148a5579SKrzysztof Parzyszek   using Schedule = omp::clause::Schedule;
48148a5579SKrzysztof Parzyszek   const auto &modifier =
49148a5579SKrzysztof Parzyszek       std::get<std::optional<Schedule::OrderingModifier>>(clause.t);
50148a5579SKrzysztof Parzyszek   if (modifier)
51148a5579SKrzysztof Parzyszek     return translateScheduleModifier(*modifier);
524d4af15cSKareem Ergawy   return mlir::omp::ScheduleModifier::none;
534d4af15cSKareem Ergawy }
544d4af15cSKareem Ergawy 
554d4af15cSKareem Ergawy static mlir::omp::ScheduleModifier
56f9e55796SKrzysztof Parzyszek getSimdModifier(const omp::clause::Schedule &clause) {
57148a5579SKrzysztof Parzyszek   using Schedule = omp::clause::Schedule;
58148a5579SKrzysztof Parzyszek   const auto &modifier =
59148a5579SKrzysztof Parzyszek       std::get<std::optional<Schedule::ChunkModifier>>(clause.t);
60148a5579SKrzysztof Parzyszek   if (modifier && *modifier == Schedule::ChunkModifier::Simd)
614d4af15cSKareem Ergawy     return mlir::omp::ScheduleModifier::simd;
624d4af15cSKareem Ergawy   return mlir::omp::ScheduleModifier::none;
634d4af15cSKareem Ergawy }
644d4af15cSKareem Ergawy 
654d4af15cSKareem Ergawy static void
667a66e420SKrzysztof Parzyszek genAllocateClause(lower::AbstractConverter &converter,
6763e70c05SKrzysztof Parzyszek                   const omp::clause::Allocate &clause,
684d4af15cSKareem Ergawy                   llvm::SmallVectorImpl<mlir::Value> &allocatorOperands,
694d4af15cSKareem Ergawy                   llvm::SmallVectorImpl<mlir::Value> &allocateOperands) {
704d4af15cSKareem Ergawy   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
714d4af15cSKareem Ergawy   mlir::Location currentLocation = converter.getCurrentLocation();
727a66e420SKrzysztof Parzyszek   lower::StatementContext stmtCtx;
734d4af15cSKareem Ergawy 
74148a5579SKrzysztof Parzyszek   auto &objects = std::get<omp::ObjectList>(clause.t);
754d4af15cSKareem Ergawy 
76148a5579SKrzysztof Parzyszek   using Allocate = omp::clause::Allocate;
77148a5579SKrzysztof Parzyszek   // ALIGN in this context is unimplemented
78148a5579SKrzysztof Parzyszek   if (std::get<std::optional<Allocate::AlignModifier>>(clause.t))
794d4af15cSKareem Ergawy     TODO(currentLocation, "OmpAllocateClause ALIGN modifier");
804d4af15cSKareem Ergawy 
814d4af15cSKareem Ergawy   // Check if allocate clause has allocator specified. If so, add it
824d4af15cSKareem Ergawy   // to list of allocators, otherwise, add default allocator to
834d4af15cSKareem Ergawy   // list of allocators.
84148a5579SKrzysztof Parzyszek   using ComplexModifier = Allocate::AllocatorComplexModifier;
85cdbd2287SKrzysztof Parzyszek   if (auto &mod = std::get<std::optional<ComplexModifier>>(clause.t)) {
86148a5579SKrzysztof Parzyszek     mlir::Value operand = fir::getBase(converter.genExprValue(mod->v, stmtCtx));
87148a5579SKrzysztof Parzyszek     allocatorOperands.append(objects.size(), operand);
884d4af15cSKareem Ergawy   } else {
8963e70c05SKrzysztof Parzyszek     mlir::Value operand = firOpBuilder.createIntegerConstant(
904d4af15cSKareem Ergawy         currentLocation, firOpBuilder.getI32Type(), 1);
91148a5579SKrzysztof Parzyszek     allocatorOperands.append(objects.size(), operand);
924d4af15cSKareem Ergawy   }
93148a5579SKrzysztof Parzyszek 
94148a5579SKrzysztof Parzyszek   genObjectList(objects, converter, allocateOperands);
954d4af15cSKareem Ergawy }
964d4af15cSKareem Ergawy 
97b4c0ef18SKareem Ergawy static mlir::omp::ClauseBindKindAttr
98b4c0ef18SKareem Ergawy genBindKindAttr(fir::FirOpBuilder &firOpBuilder,
99b4c0ef18SKareem Ergawy                 const omp::clause::Bind &clause) {
100b4c0ef18SKareem Ergawy   mlir::omp::ClauseBindKind bindKind;
101b4c0ef18SKareem Ergawy   switch (clause.v) {
102b4c0ef18SKareem Ergawy   case omp::clause::Bind::Binding::Teams:
103b4c0ef18SKareem Ergawy     bindKind = mlir::omp::ClauseBindKind::Teams;
104b4c0ef18SKareem Ergawy     break;
105b4c0ef18SKareem Ergawy   case omp::clause::Bind::Binding::Parallel:
106b4c0ef18SKareem Ergawy     bindKind = mlir::omp::ClauseBindKind::Parallel;
107b4c0ef18SKareem Ergawy     break;
108b4c0ef18SKareem Ergawy   case omp::clause::Bind::Binding::Thread:
109b4c0ef18SKareem Ergawy     bindKind = mlir::omp::ClauseBindKind::Thread;
110b4c0ef18SKareem Ergawy     break;
111b4c0ef18SKareem Ergawy   }
112b4c0ef18SKareem Ergawy   return mlir::omp::ClauseBindKindAttr::get(firOpBuilder.getContext(),
113b4c0ef18SKareem Ergawy                                             bindKind);
114b4c0ef18SKareem Ergawy }
115b4c0ef18SKareem Ergawy 
116f9e55796SKrzysztof Parzyszek static mlir::omp::ClauseProcBindKindAttr
117f9e55796SKrzysztof Parzyszek genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder,
118f9e55796SKrzysztof Parzyszek                     const omp::clause::ProcBind &clause) {
1194d4af15cSKareem Ergawy   mlir::omp::ClauseProcBindKind procBindKind;
120f9e55796SKrzysztof Parzyszek   switch (clause.v) {
121148a5579SKrzysztof Parzyszek   case omp::clause::ProcBind::AffinityPolicy::Master:
1224d4af15cSKareem Ergawy     procBindKind = mlir::omp::ClauseProcBindKind::Master;
1234d4af15cSKareem Ergawy     break;
124148a5579SKrzysztof Parzyszek   case omp::clause::ProcBind::AffinityPolicy::Close:
1254d4af15cSKareem Ergawy     procBindKind = mlir::omp::ClauseProcBindKind::Close;
1264d4af15cSKareem Ergawy     break;
127148a5579SKrzysztof Parzyszek   case omp::clause::ProcBind::AffinityPolicy::Spread:
1284d4af15cSKareem Ergawy     procBindKind = mlir::omp::ClauseProcBindKind::Spread;
1294d4af15cSKareem Ergawy     break;
130148a5579SKrzysztof Parzyszek   case omp::clause::ProcBind::AffinityPolicy::Primary:
1314d4af15cSKareem Ergawy     procBindKind = mlir::omp::ClauseProcBindKind::Primary;
1324d4af15cSKareem Ergawy     break;
1334d4af15cSKareem Ergawy   }
1344d4af15cSKareem Ergawy   return mlir::omp::ClauseProcBindKindAttr::get(firOpBuilder.getContext(),
1354d4af15cSKareem Ergawy                                                 procBindKind);
1364d4af15cSKareem Ergawy }
1374d4af15cSKareem Ergawy 
1384d4af15cSKareem Ergawy static mlir::omp::ClauseTaskDependAttr
13929d4d7f6SKrzysztof Parzyszek genDependKindAttr(lower::AbstractConverter &converter,
140f87737f3SKrzysztof Parzyszek                   const omp::clause::DependenceType kind) {
14129d4d7f6SKrzysztof Parzyszek   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
14229d4d7f6SKrzysztof Parzyszek   mlir::Location currentLocation = converter.getCurrentLocation();
14329d4d7f6SKrzysztof Parzyszek 
1444d4af15cSKareem Ergawy   mlir::omp::ClauseTaskDepend pbKind;
145148a5579SKrzysztof Parzyszek   switch (kind) {
146f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::In:
1474d4af15cSKareem Ergawy     pbKind = mlir::omp::ClauseTaskDepend::taskdependin;
1484d4af15cSKareem Ergawy     break;
149f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Out:
1504d4af15cSKareem Ergawy     pbKind = mlir::omp::ClauseTaskDepend::taskdependout;
1514d4af15cSKareem Ergawy     break;
152f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Inout:
1534d4af15cSKareem Ergawy     pbKind = mlir::omp::ClauseTaskDepend::taskdependinout;
1544d4af15cSKareem Ergawy     break;
155f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Mutexinoutset:
156cbe583b0SThirumalai Shaktivel     pbKind = mlir::omp::ClauseTaskDepend::taskdependmutexinoutset;
157cbe583b0SThirumalai Shaktivel     break;
158f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Inoutset:
159cbe583b0SThirumalai Shaktivel     pbKind = mlir::omp::ClauseTaskDepend::taskdependinoutset;
160cbe583b0SThirumalai Shaktivel     break;
161f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Depobj:
162cbe583b0SThirumalai Shaktivel     TODO(currentLocation, "DEPOBJ dependence-type");
163dcd62070SKiran Chandramohan     break;
164f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Sink:
165f87737f3SKrzysztof Parzyszek   case omp::clause::DependenceType::Source:
166148a5579SKrzysztof Parzyszek     llvm_unreachable("unhandled parser task dependence type");
1674d4af15cSKareem Ergawy     break;
1684d4af15cSKareem Ergawy   }
1694d4af15cSKareem Ergawy   return mlir::omp::ClauseTaskDependAttr::get(firOpBuilder.getContext(),
1704d4af15cSKareem Ergawy                                               pbKind);
1714d4af15cSKareem Ergawy }
1724d4af15cSKareem Ergawy 
17363e70c05SKrzysztof Parzyszek static mlir::Value
1747a66e420SKrzysztof Parzyszek getIfClauseOperand(lower::AbstractConverter &converter,
17563e70c05SKrzysztof Parzyszek                    const omp::clause::If &clause,
17663e70c05SKrzysztof Parzyszek                    omp::clause::If::DirectiveNameModifier directiveName,
1774d4af15cSKareem Ergawy                    mlir::Location clauseLocation) {
1784d4af15cSKareem Ergawy   // Only consider the clause if it's intended for the given directive.
17963e70c05SKrzysztof Parzyszek   auto &directive =
18063e70c05SKrzysztof Parzyszek       std::get<std::optional<omp::clause::If::DirectiveNameModifier>>(clause.t);
1814d4af15cSKareem Ergawy   if (directive && directive.value() != directiveName)
1824d4af15cSKareem Ergawy     return nullptr;
1834d4af15cSKareem Ergawy 
1847a66e420SKrzysztof Parzyszek   lower::StatementContext stmtCtx;
1854d4af15cSKareem Ergawy   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1864d4af15cSKareem Ergawy   mlir::Value ifVal = fir::getBase(
18763e70c05SKrzysztof Parzyszek       converter.genExprValue(std::get<omp::SomeExpr>(clause.t), stmtCtx));
1884d4af15cSKareem Ergawy   return firOpBuilder.createConvert(clauseLocation, firOpBuilder.getI1Type(),
1894d4af15cSKareem Ergawy                                     ifVal);
1904d4af15cSKareem Ergawy }
1914d4af15cSKareem Ergawy 
19278eac466SSergio Afonso static void addUseDeviceClause(
1937a66e420SKrzysztof Parzyszek     lower::AbstractConverter &converter, const omp::ObjectList &objects,
1944d4af15cSKareem Ergawy     llvm::SmallVectorImpl<mlir::Value> &operands,
1957a66e420SKrzysztof Parzyszek     llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) {
19663e70c05SKrzysztof Parzyszek   genObjectList(objects, converter, operands);
19788478a89SSergio Afonso   for (mlir::Value &operand : operands)
1984d4af15cSKareem Ergawy     checkMapType(operand.getLoc(), operand.getType());
19988478a89SSergio Afonso 
20063e70c05SKrzysztof Parzyszek   for (const omp::Object &object : objects)
2018b18f2feSKrzysztof Parzyszek     useDeviceSyms.push_back(object.sym());
2024d4af15cSKareem Ergawy }
2034d4af15cSKareem Ergawy 
2047a66e420SKrzysztof Parzyszek static void convertLoopBounds(lower::AbstractConverter &converter,
20573402634SSergio Afonso                               mlir::Location loc,
2062f3d0619SSergio Afonso                               mlir::omp::LoopRelatedClauseOps &result,
20773402634SSergio Afonso                               std::size_t loopVarTypeSize) {
20873402634SSergio Afonso   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
20973402634SSergio Afonso   // The types of lower bound, upper bound, and step are converted into the
21073402634SSergio Afonso   // type of the loop variable if necessary.
21173402634SSergio Afonso   mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
21246ecd7bbSSergio Afonso   for (unsigned it = 0; it < (unsigned)result.loopLowerBounds.size(); it++) {
21346ecd7bbSSergio Afonso     result.loopLowerBounds[it] = firOpBuilder.createConvert(
21446ecd7bbSSergio Afonso         loc, loopVarType, result.loopLowerBounds[it]);
21546ecd7bbSSergio Afonso     result.loopUpperBounds[it] = firOpBuilder.createConvert(
21646ecd7bbSSergio Afonso         loc, loopVarType, result.loopUpperBounds[it]);
21746ecd7bbSSergio Afonso     result.loopSteps[it] =
21846ecd7bbSSergio Afonso         firOpBuilder.createConvert(loc, loopVarType, result.loopSteps[it]);
21973402634SSergio Afonso   }
22073402634SSergio Afonso }
22173402634SSergio Afonso 
2224d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
2234d4af15cSKareem Ergawy // ClauseProcessor unique clauses
2244d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
2254d4af15cSKareem Ergawy 
2267c9404c2SIvan R. Ivanov bool ClauseProcessor::processBare(mlir::omp::BareClauseOps &result) const {
2277c9404c2SIvan R. Ivanov   return markClauseOccurrence<omp::clause::OmpxBare>(result.bare);
2287c9404c2SIvan R. Ivanov }
2297c9404c2SIvan R. Ivanov 
230b4c0ef18SKareem Ergawy bool ClauseProcessor::processBind(mlir::omp::BindClauseOps &result) const {
231b4c0ef18SKareem Ergawy   if (auto *clause = findUniqueClause<omp::clause::Bind>()) {
232b4c0ef18SKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
233b4c0ef18SKareem Ergawy     result.bindKind = genBindKindAttr(firOpBuilder, *clause);
234b4c0ef18SKareem Ergawy     return true;
235b4c0ef18SKareem Ergawy   }
236b4c0ef18SKareem Ergawy   return false;
237b4c0ef18SKareem Ergawy }
238b4c0ef18SKareem Ergawy 
2394d4af15cSKareem Ergawy bool ClauseProcessor::processCollapse(
2407a66e420SKrzysztof Parzyszek     mlir::Location currentLocation, lower::pft::Evaluation &eval,
2412f3d0619SSergio Afonso     mlir::omp::LoopRelatedClauseOps &result,
2427a66e420SKrzysztof Parzyszek     llvm::SmallVectorImpl<const semantics::Symbol *> &iv) const {
2434d4af15cSKareem Ergawy   bool found = false;
2444d4af15cSKareem Ergawy   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
2454d4af15cSKareem Ergawy 
2464d4af15cSKareem Ergawy   // Collect the loops to collapse.
2477a66e420SKrzysztof Parzyszek   lower::pft::Evaluation *doConstructEval = &eval.getFirstNestedEvaluation();
2487a66e420SKrzysztof Parzyszek   if (doConstructEval->getIf<parser::DoConstruct>()->IsDoConcurrent()) {
2494d4af15cSKareem Ergawy     TODO(currentLocation, "Do Concurrent in Worksharing loop construct");
2504d4af15cSKareem Ergawy   }
2514d4af15cSKareem Ergawy 
2524d4af15cSKareem Ergawy   std::int64_t collapseValue = 1l;
253f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Collapse>()) {
2547a66e420SKrzysztof Parzyszek     collapseValue = evaluate::ToInt64(clause->v).value();
2554d4af15cSKareem Ergawy     found = true;
2564d4af15cSKareem Ergawy   }
2574d4af15cSKareem Ergawy 
25873402634SSergio Afonso   std::size_t loopVarTypeSize = 0;
2594d4af15cSKareem Ergawy   do {
2607a66e420SKrzysztof Parzyszek     lower::pft::Evaluation *doLoop =
2614d4af15cSKareem Ergawy         &doConstructEval->getFirstNestedEvaluation();
2627a66e420SKrzysztof Parzyszek     auto *doStmt = doLoop->getIf<parser::NonLabelDoStmt>();
2634d4af15cSKareem Ergawy     assert(doStmt && "Expected do loop to be in the nested evaluation");
2644d4af15cSKareem Ergawy     const auto &loopControl =
2657a66e420SKrzysztof Parzyszek         std::get<std::optional<parser::LoopControl>>(doStmt->t);
2667a66e420SKrzysztof Parzyszek     const parser::LoopControl::Bounds *bounds =
2677a66e420SKrzysztof Parzyszek         std::get_if<parser::LoopControl::Bounds>(&loopControl->u);
2684d4af15cSKareem Ergawy     assert(bounds && "Expected bounds for worksharing do loop");
2697a66e420SKrzysztof Parzyszek     lower::StatementContext stmtCtx;
27046ecd7bbSSergio Afonso     result.loopLowerBounds.push_back(fir::getBase(
2717a66e420SKrzysztof Parzyszek         converter.genExprValue(*semantics::GetExpr(bounds->lower), stmtCtx)));
27246ecd7bbSSergio Afonso     result.loopUpperBounds.push_back(fir::getBase(
2737a66e420SKrzysztof Parzyszek         converter.genExprValue(*semantics::GetExpr(bounds->upper), stmtCtx)));
2744d4af15cSKareem Ergawy     if (bounds->step) {
27546ecd7bbSSergio Afonso       result.loopSteps.push_back(fir::getBase(
2767a66e420SKrzysztof Parzyszek           converter.genExprValue(*semantics::GetExpr(bounds->step), stmtCtx)));
2774d4af15cSKareem Ergawy     } else { // If `step` is not present, assume it as `1`.
27846ecd7bbSSergio Afonso       result.loopSteps.push_back(firOpBuilder.createIntegerConstant(
2794d4af15cSKareem Ergawy           currentLocation, firOpBuilder.getIntegerType(32), 1));
2804d4af15cSKareem Ergawy     }
2814d4af15cSKareem Ergawy     iv.push_back(bounds->name.thing.symbol);
2824d4af15cSKareem Ergawy     loopVarTypeSize = std::max(loopVarTypeSize,
2834d4af15cSKareem Ergawy                                bounds->name.thing.symbol->GetUltimate().size());
2844d4af15cSKareem Ergawy     collapseValue--;
2854d4af15cSKareem Ergawy     doConstructEval =
2864d4af15cSKareem Ergawy         &*std::next(doConstructEval->getNestedEvaluations().begin());
2874d4af15cSKareem Ergawy   } while (collapseValue > 0);
2884d4af15cSKareem Ergawy 
28978eac466SSergio Afonso   convertLoopBounds(converter, currentLocation, result, loopVarTypeSize);
29073402634SSergio Afonso 
2914d4af15cSKareem Ergawy   return found;
2924d4af15cSKareem Ergawy }
2934d4af15cSKareem Ergawy 
2947a66e420SKrzysztof Parzyszek bool ClauseProcessor::processDevice(lower::StatementContext &stmtCtx,
29578eac466SSergio Afonso                                     mlir::omp::DeviceClauseOps &result) const {
2967a66e420SKrzysztof Parzyszek   const parser::CharBlock *source = nullptr;
297f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Device>(&source)) {
2984d4af15cSKareem Ergawy     mlir::Location clauseLocation = converter.genLocation(*source);
299f9e55796SKrzysztof Parzyszek     if (auto deviceModifier =
300f9e55796SKrzysztof Parzyszek             std::get<std::optional<omp::clause::Device::DeviceModifier>>(
301f9e55796SKrzysztof Parzyszek                 clause->t)) {
302f9e55796SKrzysztof Parzyszek       if (deviceModifier == omp::clause::Device::DeviceModifier::Ancestor) {
3034d4af15cSKareem Ergawy         TODO(clauseLocation, "OMPD_target Device Modifier Ancestor");
3044d4af15cSKareem Ergawy       }
3054d4af15cSKareem Ergawy     }
306f9e55796SKrzysztof Parzyszek     const auto &deviceExpr = std::get<omp::SomeExpr>(clause->t);
307fdfeea5bSSergio Afonso     result.device = fir::getBase(converter.genExprValue(deviceExpr, stmtCtx));
3084d4af15cSKareem Ergawy     return true;
3094d4af15cSKareem Ergawy   }
3104d4af15cSKareem Ergawy   return false;
3114d4af15cSKareem Ergawy }
3124d4af15cSKareem Ergawy 
3134d4af15cSKareem Ergawy bool ClauseProcessor::processDeviceType(
31478eac466SSergio Afonso     mlir::omp::DeviceTypeClauseOps &result) const {
315f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::DeviceType>()) {
3164d4af15cSKareem Ergawy     // Case: declare target ... device_type(any | host | nohost)
317f9e55796SKrzysztof Parzyszek     switch (clause->v) {
318148a5579SKrzysztof Parzyszek     case omp::clause::DeviceType::DeviceTypeDescription::Nohost:
31978eac466SSergio Afonso       result.deviceType = mlir::omp::DeclareTargetDeviceType::nohost;
3204d4af15cSKareem Ergawy       break;
321148a5579SKrzysztof Parzyszek     case omp::clause::DeviceType::DeviceTypeDescription::Host:
32278eac466SSergio Afonso       result.deviceType = mlir::omp::DeclareTargetDeviceType::host;
3234d4af15cSKareem Ergawy       break;
324148a5579SKrzysztof Parzyszek     case omp::clause::DeviceType::DeviceTypeDescription::Any:
32578eac466SSergio Afonso       result.deviceType = mlir::omp::DeclareTargetDeviceType::any;
3264d4af15cSKareem Ergawy       break;
3274d4af15cSKareem Ergawy     }
3284d4af15cSKareem Ergawy     return true;
3294d4af15cSKareem Ergawy   }
3304d4af15cSKareem Ergawy   return false;
3314d4af15cSKareem Ergawy }
3324d4af15cSKareem Ergawy 
333fc1c34bbSSergio Afonso bool ClauseProcessor::processDistSchedule(
334fc1c34bbSSergio Afonso     lower::StatementContext &stmtCtx,
335fc1c34bbSSergio Afonso     mlir::omp::DistScheduleClauseOps &result) const {
336fc1c34bbSSergio Afonso   if (auto *clause = findUniqueClause<omp::clause::DistSchedule>()) {
337fdfeea5bSSergio Afonso     result.distScheduleStatic = converter.getFirOpBuilder().getUnitAttr();
338fc1c34bbSSergio Afonso     const auto &chunkSize = std::get<std::optional<ExprTy>>(clause->t);
339fc1c34bbSSergio Afonso     if (chunkSize)
340fdfeea5bSSergio Afonso       result.distScheduleChunkSize =
341fc1c34bbSSergio Afonso           fir::getBase(converter.genExprValue(*chunkSize, stmtCtx));
342fc1c34bbSSergio Afonso     return true;
343fc1c34bbSSergio Afonso   }
344fc1c34bbSSergio Afonso   return false;
345fc1c34bbSSergio Afonso }
346fc1c34bbSSergio Afonso 
347e34e739bSAnchu Rajendran S bool ClauseProcessor::processFilter(lower::StatementContext &stmtCtx,
348e34e739bSAnchu Rajendran S                                     mlir::omp::FilterClauseOps &result) const {
349e34e739bSAnchu Rajendran S   if (auto *clause = findUniqueClause<omp::clause::Filter>()) {
350fdfeea5bSSergio Afonso     result.filteredThreadId =
351e34e739bSAnchu Rajendran S         fir::getBase(converter.genExprValue(clause->v, stmtCtx));
352e34e739bSAnchu Rajendran S     return true;
353e34e739bSAnchu Rajendran S   }
354e34e739bSAnchu Rajendran S   return false;
355e34e739bSAnchu Rajendran S }
356e34e739bSAnchu Rajendran S 
3577a66e420SKrzysztof Parzyszek bool ClauseProcessor::processFinal(lower::StatementContext &stmtCtx,
35878eac466SSergio Afonso                                    mlir::omp::FinalClauseOps &result) const {
3597a66e420SKrzysztof Parzyszek   const parser::CharBlock *source = nullptr;
360f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Final>(&source)) {
3614d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
3624d4af15cSKareem Ergawy     mlir::Location clauseLocation = converter.genLocation(*source);
3634d4af15cSKareem Ergawy 
364f9e55796SKrzysztof Parzyszek     mlir::Value finalVal =
365f9e55796SKrzysztof Parzyszek         fir::getBase(converter.genExprValue(clause->v, stmtCtx));
366fdfeea5bSSergio Afonso     result.final = firOpBuilder.createConvert(
36778eac466SSergio Afonso         clauseLocation, firOpBuilder.getI1Type(), finalVal);
3684d4af15cSKareem Ergawy     return true;
3694d4af15cSKareem Ergawy   }
3704d4af15cSKareem Ergawy   return false;
3714d4af15cSKareem Ergawy }
3724d4af15cSKareem Ergawy 
37378eac466SSergio Afonso bool ClauseProcessor::processHint(mlir::omp::HintClauseOps &result) const {
374f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Hint>()) {
3754d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
3767a66e420SKrzysztof Parzyszek     int64_t hintValue = *evaluate::ToInt64(clause->v);
377fdfeea5bSSergio Afonso     result.hint = firOpBuilder.getI64IntegerAttr(hintValue);
3784d4af15cSKareem Ergawy     return true;
3794d4af15cSKareem Ergawy   }
3804d4af15cSKareem Ergawy   return false;
3814d4af15cSKareem Ergawy }
3824d4af15cSKareem Ergawy 
38378eac466SSergio Afonso bool ClauseProcessor::processMergeable(
38478eac466SSergio Afonso     mlir::omp::MergeableClauseOps &result) const {
385fdfeea5bSSergio Afonso   return markClauseOccurrence<omp::clause::Mergeable>(result.mergeable);
3864d4af15cSKareem Ergawy }
3874d4af15cSKareem Ergawy 
38878eac466SSergio Afonso bool ClauseProcessor::processNowait(mlir::omp::NowaitClauseOps &result) const {
389fdfeea5bSSergio Afonso   return markClauseOccurrence<omp::clause::Nowait>(result.nowait);
3904d4af15cSKareem Ergawy }
3914d4af15cSKareem Ergawy 
39278eac466SSergio Afonso bool ClauseProcessor::processNumTeams(
3937a66e420SKrzysztof Parzyszek     lower::StatementContext &stmtCtx,
39478eac466SSergio Afonso     mlir::omp::NumTeamsClauseOps &result) const {
3954d4af15cSKareem Ergawy   // TODO Get lower and upper bounds for num_teams when parser is updated to
3964d4af15cSKareem Ergawy   // accept both.
397f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::NumTeams>()) {
39830646461SKrzysztof Parzyszek     // The num_teams directive accepts a list of team lower/upper bounds.
39930646461SKrzysztof Parzyszek     // This is an extension to support grid specification for ompx_bare.
40030646461SKrzysztof Parzyszek     // Here, only expect a single element in the list.
40130646461SKrzysztof Parzyszek     assert(clause->v.size() == 1);
40230646461SKrzysztof Parzyszek     // auto lowerBound = std::get<std::optional<ExprTy>>(clause->v[0]->t);
40330646461SKrzysztof Parzyszek     auto &upperBound = std::get<ExprTy>(clause->v[0].t);
404fdfeea5bSSergio Afonso     result.numTeamsUpper =
40578eac466SSergio Afonso         fir::getBase(converter.genExprValue(upperBound, stmtCtx));
4064d4af15cSKareem Ergawy     return true;
4074d4af15cSKareem Ergawy   }
4084d4af15cSKareem Ergawy   return false;
4094d4af15cSKareem Ergawy }
4104d4af15cSKareem Ergawy 
4114d4af15cSKareem Ergawy bool ClauseProcessor::processNumThreads(
4127a66e420SKrzysztof Parzyszek     lower::StatementContext &stmtCtx,
41378eac466SSergio Afonso     mlir::omp::NumThreadsClauseOps &result) const {
414f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::NumThreads>()) {
4154d4af15cSKareem Ergawy     // OMPIRBuilder expects `NUM_THREADS` clause as a `Value`.
416fdfeea5bSSergio Afonso     result.numThreads =
41778eac466SSergio Afonso         fir::getBase(converter.genExprValue(clause->v, stmtCtx));
4184d4af15cSKareem Ergawy     return true;
4194d4af15cSKareem Ergawy   }
4204d4af15cSKareem Ergawy   return false;
4214d4af15cSKareem Ergawy }
4224d4af15cSKareem Ergawy 
423b4ab52c8Sharishch4 bool ClauseProcessor::processOrder(mlir::omp::OrderClauseOps &result) const {
424b4ab52c8Sharishch4   using Order = omp::clause::Order;
425b4ab52c8Sharishch4   if (auto *clause = findUniqueClause<Order>()) {
426b4ab52c8Sharishch4     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
427fdfeea5bSSergio Afonso     result.order = mlir::omp::ClauseOrderKindAttr::get(
428b4ab52c8Sharishch4         firOpBuilder.getContext(), mlir::omp::ClauseOrderKind::Concurrent);
429b4ab52c8Sharishch4     const auto &modifier =
430b4ab52c8Sharishch4         std::get<std::optional<Order::OrderModifier>>(clause->t);
431b4ab52c8Sharishch4     if (modifier && *modifier == Order::OrderModifier::Unconstrained) {
432fdfeea5bSSergio Afonso       result.orderMod = mlir::omp::OrderModifierAttr::get(
433b4ab52c8Sharishch4           firOpBuilder.getContext(), mlir::omp::OrderModifier::unconstrained);
434b4ab52c8Sharishch4     } else {
435b4ab52c8Sharishch4       // "If order-modifier is not unconstrained, the behavior is as if the
436b4ab52c8Sharishch4       // reproducible modifier is present."
437fdfeea5bSSergio Afonso       result.orderMod = mlir::omp::OrderModifierAttr::get(
438b4ab52c8Sharishch4           firOpBuilder.getContext(), mlir::omp::OrderModifier::reproducible);
439b4ab52c8Sharishch4     }
440b4ab52c8Sharishch4     return true;
441b4ab52c8Sharishch4   }
442b4ab52c8Sharishch4   return false;
443b4ab52c8Sharishch4 }
444b4ab52c8Sharishch4 
44578eac466SSergio Afonso bool ClauseProcessor::processOrdered(
44678eac466SSergio Afonso     mlir::omp::OrderedClauseOps &result) const {
447f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Ordered>()) {
4484d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
4494d4af15cSKareem Ergawy     int64_t orderedClauseValue = 0l;
450f9e55796SKrzysztof Parzyszek     if (clause->v.has_value())
4517a66e420SKrzysztof Parzyszek       orderedClauseValue = *evaluate::ToInt64(*clause->v);
452fdfeea5bSSergio Afonso     result.ordered = firOpBuilder.getI64IntegerAttr(orderedClauseValue);
4534d4af15cSKareem Ergawy     return true;
4544d4af15cSKareem Ergawy   }
4554d4af15cSKareem Ergawy   return false;
4564d4af15cSKareem Ergawy }
4574d4af15cSKareem Ergawy 
45878eac466SSergio Afonso bool ClauseProcessor::processPriority(
4597a66e420SKrzysztof Parzyszek     lower::StatementContext &stmtCtx,
46078eac466SSergio Afonso     mlir::omp::PriorityClauseOps &result) const {
461f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Priority>()) {
462fdfeea5bSSergio Afonso     result.priority = fir::getBase(converter.genExprValue(clause->v, stmtCtx));
4634d4af15cSKareem Ergawy     return true;
4644d4af15cSKareem Ergawy   }
4654d4af15cSKareem Ergawy   return false;
4664d4af15cSKareem Ergawy }
4674d4af15cSKareem Ergawy 
468edc50f39SNimishMishra bool ClauseProcessor::processDetach(mlir::omp::DetachClauseOps &result) const {
469edc50f39SNimishMishra   if (auto *clause = findUniqueClause<omp::clause::Detach>()) {
470edc50f39SNimishMishra     semantics::Symbol *sym = clause->v.sym();
471edc50f39SNimishMishra     mlir::Value symVal = converter.getSymbolAddress(*sym);
472edc50f39SNimishMishra     result.eventHandle = symVal;
473edc50f39SNimishMishra     return true;
474edc50f39SNimishMishra   }
475edc50f39SNimishMishra   return false;
476edc50f39SNimishMishra }
477edc50f39SNimishMishra 
4784d4af15cSKareem Ergawy bool ClauseProcessor::processProcBind(
47978eac466SSergio Afonso     mlir::omp::ProcBindClauseOps &result) const {
480f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::ProcBind>()) {
4814d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
482fdfeea5bSSergio Afonso     result.procBindKind = genProcBindKindAttr(firOpBuilder, *clause);
4834d4af15cSKareem Ergawy     return true;
4844d4af15cSKareem Ergawy   }
4854d4af15cSKareem Ergawy   return false;
4864d4af15cSKareem Ergawy }
4874d4af15cSKareem Ergawy 
48878eac466SSergio Afonso bool ClauseProcessor::processSafelen(
48978eac466SSergio Afonso     mlir::omp::SafelenClauseOps &result) const {
490f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Safelen>()) {
4914d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
4927a66e420SKrzysztof Parzyszek     const std::optional<std::int64_t> safelenVal = evaluate::ToInt64(clause->v);
493fdfeea5bSSergio Afonso     result.safelen = firOpBuilder.getI64IntegerAttr(*safelenVal);
4944d4af15cSKareem Ergawy     return true;
4954d4af15cSKareem Ergawy   }
4964d4af15cSKareem Ergawy   return false;
4974d4af15cSKareem Ergawy }
4984d4af15cSKareem Ergawy 
4994d4af15cSKareem Ergawy bool ClauseProcessor::processSchedule(
5007a66e420SKrzysztof Parzyszek     lower::StatementContext &stmtCtx,
50178eac466SSergio Afonso     mlir::omp::ScheduleClauseOps &result) const {
502f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Schedule>()) {
5034d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
5044d4af15cSKareem Ergawy     mlir::MLIRContext *context = firOpBuilder.getContext();
505148a5579SKrzysztof Parzyszek     const auto &scheduleType = std::get<omp::clause::Schedule::Kind>(clause->t);
5064d4af15cSKareem Ergawy 
5074d4af15cSKareem Ergawy     mlir::omp::ClauseScheduleKind scheduleKind;
508f9e55796SKrzysztof Parzyszek     switch (scheduleType) {
509148a5579SKrzysztof Parzyszek     case omp::clause::Schedule::Kind::Static:
5104d4af15cSKareem Ergawy       scheduleKind = mlir::omp::ClauseScheduleKind::Static;
5114d4af15cSKareem Ergawy       break;
512148a5579SKrzysztof Parzyszek     case omp::clause::Schedule::Kind::Dynamic:
5134d4af15cSKareem Ergawy       scheduleKind = mlir::omp::ClauseScheduleKind::Dynamic;
5144d4af15cSKareem Ergawy       break;
515148a5579SKrzysztof Parzyszek     case omp::clause::Schedule::Kind::Guided:
5164d4af15cSKareem Ergawy       scheduleKind = mlir::omp::ClauseScheduleKind::Guided;
5174d4af15cSKareem Ergawy       break;
518148a5579SKrzysztof Parzyszek     case omp::clause::Schedule::Kind::Auto:
5194d4af15cSKareem Ergawy       scheduleKind = mlir::omp::ClauseScheduleKind::Auto;
5204d4af15cSKareem Ergawy       break;
521148a5579SKrzysztof Parzyszek     case omp::clause::Schedule::Kind::Runtime:
5224d4af15cSKareem Ergawy       scheduleKind = mlir::omp::ClauseScheduleKind::Runtime;
5234d4af15cSKareem Ergawy       break;
5244d4af15cSKareem Ergawy     }
5254d4af15cSKareem Ergawy 
526fdfeea5bSSergio Afonso     result.scheduleKind =
52778eac466SSergio Afonso         mlir::omp::ClauseScheduleKindAttr::get(context, scheduleKind);
5284d4af15cSKareem Ergawy 
529fdfeea5bSSergio Afonso     mlir::omp::ScheduleModifier scheduleMod = getScheduleModifier(*clause);
530fdfeea5bSSergio Afonso     if (scheduleMod != mlir::omp::ScheduleModifier::none)
531fdfeea5bSSergio Afonso       result.scheduleMod =
532fdfeea5bSSergio Afonso           mlir::omp::ScheduleModifierAttr::get(context, scheduleMod);
5334d4af15cSKareem Ergawy 
534f9e55796SKrzysztof Parzyszek     if (getSimdModifier(*clause) != mlir::omp::ScheduleModifier::none)
535fdfeea5bSSergio Afonso       result.scheduleSimd = firOpBuilder.getUnitAttr();
5364d4af15cSKareem Ergawy 
537f9e55796SKrzysztof Parzyszek     if (const auto &chunkExpr = std::get<omp::MaybeExpr>(clause->t))
538fdfeea5bSSergio Afonso       result.scheduleChunk =
53978eac466SSergio Afonso           fir::getBase(converter.genExprValue(*chunkExpr, stmtCtx));
54078eac466SSergio Afonso 
5414d4af15cSKareem Ergawy     return true;
5424d4af15cSKareem Ergawy   }
5434d4af15cSKareem Ergawy   return false;
5444d4af15cSKareem Ergawy }
5454d4af15cSKareem Ergawy 
54678eac466SSergio Afonso bool ClauseProcessor::processSimdlen(
54778eac466SSergio Afonso     mlir::omp::SimdlenClauseOps &result) const {
548f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::Simdlen>()) {
5494d4af15cSKareem Ergawy     fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
5507a66e420SKrzysztof Parzyszek     const std::optional<std::int64_t> simdlenVal = evaluate::ToInt64(clause->v);
551fdfeea5bSSergio Afonso     result.simdlen = firOpBuilder.getI64IntegerAttr(*simdlenVal);
5524d4af15cSKareem Ergawy     return true;
5534d4af15cSKareem Ergawy   }
5544d4af15cSKareem Ergawy   return false;
5554d4af15cSKareem Ergawy }
5564d4af15cSKareem Ergawy 
5574d4af15cSKareem Ergawy bool ClauseProcessor::processThreadLimit(
5587a66e420SKrzysztof Parzyszek     lower::StatementContext &stmtCtx,
55978eac466SSergio Afonso     mlir::omp::ThreadLimitClauseOps &result) const {
560f9e55796SKrzysztof Parzyszek   if (auto *clause = findUniqueClause<omp::clause::ThreadLimit>()) {
561fdfeea5bSSergio Afonso     result.threadLimit =
56278eac466SSergio Afonso         fir::getBase(converter.genExprValue(clause->v, stmtCtx));
5634d4af15cSKareem Ergawy     return true;
5644d4af15cSKareem Ergawy   }
5654d4af15cSKareem Ergawy   return false;
5664d4af15cSKareem Ergawy }
5674d4af15cSKareem Ergawy 
56878eac466SSergio Afonso bool ClauseProcessor::processUntied(mlir::omp::UntiedClauseOps &result) const {
569fdfeea5bSSergio Afonso   return markClauseOccurrence<omp::clause::Untied>(result.untied);
5704d4af15cSKareem Ergawy }
5714d4af15cSKareem Ergawy 
5724d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
5734d4af15cSKareem Ergawy // ClauseProcessor repeatable clauses
5744d4af15cSKareem Ergawy //===----------------------------------------------------------------------===//
5757ffeaf0eSharishch4 static llvm::StringMap<bool> getTargetFeatures(mlir::ModuleOp module) {
5767ffeaf0eSharishch4   llvm::StringMap<bool> featuresMap;
5777ffeaf0eSharishch4   llvm::SmallVector<llvm::StringRef> targetFeaturesVec;
5787ffeaf0eSharishch4   if (mlir::LLVM::TargetFeaturesAttr features =
5797ffeaf0eSharishch4           fir::getTargetFeatures(module)) {
5807ffeaf0eSharishch4     llvm::ArrayRef<mlir::StringAttr> featureAttrs = features.getFeatures();
5817ffeaf0eSharishch4     for (auto &featureAttr : featureAttrs) {
5827ffeaf0eSharishch4       llvm::StringRef featureKeyString = featureAttr.strref();
5837ffeaf0eSharishch4       featuresMap[featureKeyString.substr(1)] = (featureKeyString[0] == '+');
5847ffeaf0eSharishch4     }
5857ffeaf0eSharishch4   }
5867ffeaf0eSharishch4   return featuresMap;
5877ffeaf0eSharishch4 }
5887ffeaf0eSharishch4 
5897ffeaf0eSharishch4 static void
5907ffeaf0eSharishch4 addAlignedClause(lower::AbstractConverter &converter,
5917ffeaf0eSharishch4                  const omp::clause::Aligned &clause,
5927ffeaf0eSharishch4                  llvm::SmallVectorImpl<mlir::Value> &alignedVars,
593fdfeea5bSSergio Afonso                  llvm::SmallVectorImpl<mlir::Attribute> &alignments) {
5947ffeaf0eSharishch4   using Aligned = omp::clause::Aligned;
5957ffeaf0eSharishch4   lower::StatementContext stmtCtx;
5967ffeaf0eSharishch4   mlir::IntegerAttr alignmentValueAttr;
5977ffeaf0eSharishch4   int64_t alignment = 0;
5987ffeaf0eSharishch4   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
5997ffeaf0eSharishch4 
6007ffeaf0eSharishch4   if (auto &alignmentValueParserExpr =
6017ffeaf0eSharishch4           std::get<std::optional<Aligned::Alignment>>(clause.t)) {
6027ffeaf0eSharishch4     mlir::Value operand = fir::getBase(
6037ffeaf0eSharishch4         converter.genExprValue(*alignmentValueParserExpr, stmtCtx));
6047ffeaf0eSharishch4     alignment = *fir::getIntIfConstant(operand);
6057ffeaf0eSharishch4   } else {
6067ffeaf0eSharishch4     llvm::StringMap<bool> featuresMap = getTargetFeatures(builder.getModule());
6077ffeaf0eSharishch4     llvm::Triple triple = fir::getTargetTriple(builder.getModule());
6087ffeaf0eSharishch4     alignment =
6097ffeaf0eSharishch4         llvm::OpenMPIRBuilder::getOpenMPDefaultSimdAlign(triple, featuresMap);
6107ffeaf0eSharishch4   }
6117ffeaf0eSharishch4 
6127ffeaf0eSharishch4   // The default alignment for some targets is equal to 0.
6137ffeaf0eSharishch4   // Do not generate alignment assumption if alignment is less than or equal to
6147ffeaf0eSharishch4   // 0.
6157ffeaf0eSharishch4   if (alignment > 0) {
616d3eb65f1SKaviya Rajendiran     // alignment value must be power of 2
617d3eb65f1SKaviya Rajendiran     assert((alignment & (alignment - 1)) == 0 && "alignment is not power of 2");
6187ffeaf0eSharishch4     auto &objects = std::get<omp::ObjectList>(clause.t);
6197ffeaf0eSharishch4     if (!objects.empty())
6207ffeaf0eSharishch4       genObjectList(objects, converter, alignedVars);
6217ffeaf0eSharishch4     alignmentValueAttr = builder.getI64IntegerAttr(alignment);
6227ffeaf0eSharishch4     // All the list items in a aligned clause will have same alignment
6237ffeaf0eSharishch4     for (std::size_t i = 0; i < objects.size(); i++)
624fdfeea5bSSergio Afonso       alignments.push_back(alignmentValueAttr);
6257ffeaf0eSharishch4   }
6267ffeaf0eSharishch4 }
6277ffeaf0eSharishch4 
6287ffeaf0eSharishch4 bool ClauseProcessor::processAligned(
6297ffeaf0eSharishch4     mlir::omp::AlignedClauseOps &result) const {
6307ffeaf0eSharishch4   return findRepeatableClause<omp::clause::Aligned>(
6317ffeaf0eSharishch4       [&](const omp::clause::Aligned &clause, const parser::CharBlock &) {
6327ffeaf0eSharishch4         addAlignedClause(converter, clause, result.alignedVars,
633fdfeea5bSSergio Afonso                          result.alignments);
6347ffeaf0eSharishch4       });
6357ffeaf0eSharishch4 }
6364d4af15cSKareem Ergawy 
6374d4af15cSKareem Ergawy bool ClauseProcessor::processAllocate(
63878eac466SSergio Afonso     mlir::omp::AllocateClauseOps &result) const {
63963e70c05SKrzysztof Parzyszek   return findRepeatableClause<omp::clause::Allocate>(
6407a66e420SKrzysztof Parzyszek       [&](const omp::clause::Allocate &clause, const parser::CharBlock &) {
64178eac466SSergio Afonso         genAllocateClause(converter, clause, result.allocatorVars,
64278eac466SSergio Afonso                           result.allocateVars);
6434d4af15cSKareem Ergawy       });
6444d4af15cSKareem Ergawy }
6454d4af15cSKareem Ergawy 
6464d4af15cSKareem Ergawy bool ClauseProcessor::processCopyin() const {
6474d4af15cSKareem Ergawy   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
6484d4af15cSKareem Ergawy   mlir::OpBuilder::InsertPoint insPt = firOpBuilder.saveInsertionPoint();
6494d4af15cSKareem Ergawy   firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
6504d4af15cSKareem Ergawy   auto checkAndCopyHostAssociateVar =
6517a66e420SKrzysztof Parzyszek       [&](semantics::Symbol *sym,
6524d4af15cSKareem Ergawy           mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr) {
6537a66e420SKrzysztof Parzyszek         assert(sym->has<semantics::HostAssocDetails>() &&
6544d4af15cSKareem Ergawy                "No host-association found");
6554d4af15cSKareem Ergawy         if (converter.isPresentShallowLookup(*sym))
6564d4af15cSKareem Ergawy           converter.copyHostAssociateVar(*sym, copyAssignIP);
6574d4af15cSKareem Ergawy       };
65863e70c05SKrzysztof Parzyszek   bool hasCopyin = findRepeatableClause<omp::clause::Copyin>(
6597a66e420SKrzysztof Parzyszek       [&](const omp::clause::Copyin &clause, const parser::CharBlock &) {
66063e70c05SKrzysztof Parzyszek         for (const omp::Object &object : clause.v) {
6618b18f2feSKrzysztof Parzyszek           semantics::Symbol *sym = object.sym();
66263e70c05SKrzysztof Parzyszek           assert(sym && "Expecting symbol");
6634d4af15cSKareem Ergawy           if (const auto *commonDetails =
6647a66e420SKrzysztof Parzyszek                   sym->detailsIf<semantics::CommonBlockDetails>()) {
6654d4af15cSKareem Ergawy             for (const auto &mem : commonDetails->objects())
6664d4af15cSKareem Ergawy               checkAndCopyHostAssociateVar(&*mem, &insPt);
6674d4af15cSKareem Ergawy             break;
6684d4af15cSKareem Ergawy           }
66953b59022SDavid Truby 
6707a66e420SKrzysztof Parzyszek           assert(sym->has<semantics::HostAssocDetails>() &&
6714d4af15cSKareem Ergawy                  "No host-association found");
6724d4af15cSKareem Ergawy           checkAndCopyHostAssociateVar(sym);
6734d4af15cSKareem Ergawy         }
6744d4af15cSKareem Ergawy       });
6754d4af15cSKareem Ergawy 
6764d4af15cSKareem Ergawy   // [OMP 5.0, 2.19.6.1] The copy is done after the team is formed and prior to
6774d4af15cSKareem Ergawy   // the execution of the associated structured block. Emit implicit barrier to
6784d4af15cSKareem Ergawy   // synchronize threads and avoid data races on propagation master's thread
6794d4af15cSKareem Ergawy   // values of threadprivate variables to local instances of that variables of
6804d4af15cSKareem Ergawy   // all other implicit threads.
68194204f59SKrzysztof Parzyszek 
68294204f59SKrzysztof Parzyszek   // All copies are inserted at either "insPt" (i.e. immediately before it),
68394204f59SKrzysztof Parzyszek   // or at some earlier point (as determined by "copyHostAssociateVar").
68494204f59SKrzysztof Parzyszek   // Unless the insertion point is given to "copyHostAssociateVar" explicitly,
68594204f59SKrzysztof Parzyszek   // it will not restore the builder's insertion point. Since the copies may be
68694204f59SKrzysztof Parzyszek   // inserted in any order (not following the execution order), make sure the
68794204f59SKrzysztof Parzyszek   // barrier is inserted following all of them.
68894204f59SKrzysztof Parzyszek   firOpBuilder.restoreInsertionPoint(insPt);
6894d4af15cSKareem Ergawy   if (hasCopyin)
6904d4af15cSKareem Ergawy     firOpBuilder.create<mlir::omp::BarrierOp>(converter.getCurrentLocation());
6914d4af15cSKareem Ergawy   return hasCopyin;
6924d4af15cSKareem Ergawy }
6934d4af15cSKareem Ergawy 
694e50a231dSLeandro Lupori /// Class that extracts information from the specified type.
695e50a231dSLeandro Lupori class TypeInfo {
696e50a231dSLeandro Lupori public:
697e50a231dSLeandro Lupori   TypeInfo(mlir::Type ty) { typeScan(ty); }
698e50a231dSLeandro Lupori 
699e50a231dSLeandro Lupori   // Returns the length of character types.
700e50a231dSLeandro Lupori   std::optional<fir::CharacterType::LenType> getCharLength() const {
701e50a231dSLeandro Lupori     return charLen;
702e50a231dSLeandro Lupori   }
703e50a231dSLeandro Lupori 
704e50a231dSLeandro Lupori   // Returns the shape of array types.
705d671ebe4SSergio Afonso   llvm::ArrayRef<int64_t> getShape() const { return shape; }
706e50a231dSLeandro Lupori 
707e50a231dSLeandro Lupori   // Is the type inside a box?
708e50a231dSLeandro Lupori   bool isBox() const { return inBox; }
709e50a231dSLeandro Lupori 
710e50a231dSLeandro Lupori private:
711e50a231dSLeandro Lupori   void typeScan(mlir::Type type);
712e50a231dSLeandro Lupori 
713e50a231dSLeandro Lupori   std::optional<fir::CharacterType::LenType> charLen;
714e50a231dSLeandro Lupori   llvm::SmallVector<int64_t> shape;
715e50a231dSLeandro Lupori   bool inBox = false;
716e50a231dSLeandro Lupori };
717e50a231dSLeandro Lupori 
718e50a231dSLeandro Lupori void TypeInfo::typeScan(mlir::Type ty) {
719e50a231dSLeandro Lupori   if (auto sty = mlir::dyn_cast<fir::SequenceType>(ty)) {
720e50a231dSLeandro Lupori     assert(shape.empty() && !sty.getShape().empty());
721e50a231dSLeandro Lupori     shape = llvm::SmallVector<int64_t>(sty.getShape());
722e50a231dSLeandro Lupori     typeScan(sty.getEleTy());
723e50a231dSLeandro Lupori   } else if (auto bty = mlir::dyn_cast<fir::BoxType>(ty)) {
724e50a231dSLeandro Lupori     inBox = true;
725e50a231dSLeandro Lupori     typeScan(bty.getEleTy());
726e50a231dSLeandro Lupori   } else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
727e50a231dSLeandro Lupori     charLen = cty.getLen();
728e50a231dSLeandro Lupori   } else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
729e50a231dSLeandro Lupori     typeScan(hty.getEleTy());
730e50a231dSLeandro Lupori   } else if (auto pty = mlir::dyn_cast<fir::PointerType>(ty)) {
731e50a231dSLeandro Lupori     typeScan(pty.getEleTy());
732e50a231dSLeandro Lupori   } else {
733e50a231dSLeandro Lupori     // The scan ends when reaching any built-in or record type.
734c4204c0bSjeanPerier     assert(ty.isIntOrIndexOrFloat() || mlir::isa<mlir::ComplexType>(ty) ||
735e50a231dSLeandro Lupori            mlir::isa<fir::LogicalType>(ty) || mlir::isa<fir::RecordType>(ty));
736e50a231dSLeandro Lupori   }
737e50a231dSLeandro Lupori }
738e50a231dSLeandro Lupori 
739e50a231dSLeandro Lupori // Create a function that performs a copy between two variables, compatible
740e50a231dSLeandro Lupori // with their types and attributes.
741e50a231dSLeandro Lupori static mlir::func::FuncOp
7427a66e420SKrzysztof Parzyszek createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
743e50a231dSLeandro Lupori                mlir::Type varType, fir::FortranVariableFlagsEnum varAttrs) {
744e50a231dSLeandro Lupori   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
745e50a231dSLeandro Lupori   mlir::ModuleOp module = builder.getModule();
746e50a231dSLeandro Lupori   mlir::Type eleTy = mlir::cast<fir::ReferenceType>(varType).getEleTy();
747e50a231dSLeandro Lupori   TypeInfo typeInfo(eleTy);
748e50a231dSLeandro Lupori   std::string copyFuncName =
749e50a231dSLeandro Lupori       fir::getTypeAsString(eleTy, builder.getKindMap(), "_copy");
750e50a231dSLeandro Lupori 
751e50a231dSLeandro Lupori   if (auto decl = module.lookupSymbol<mlir::func::FuncOp>(copyFuncName))
752e50a231dSLeandro Lupori     return decl;
753e50a231dSLeandro Lupori 
754e50a231dSLeandro Lupori   // create function
755e50a231dSLeandro Lupori   mlir::OpBuilder::InsertionGuard guard(builder);
756e50a231dSLeandro Lupori   mlir::OpBuilder modBuilder(module.getBodyRegion());
757e50a231dSLeandro Lupori   llvm::SmallVector<mlir::Type> argsTy = {varType, varType};
758e50a231dSLeandro Lupori   auto funcType = mlir::FunctionType::get(builder.getContext(), argsTy, {});
759e50a231dSLeandro Lupori   mlir::func::FuncOp funcOp =
760e50a231dSLeandro Lupori       modBuilder.create<mlir::func::FuncOp>(loc, copyFuncName, funcType);
761e50a231dSLeandro Lupori   funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
762261a4026SMichael Klemm   fir::factory::setInternalLinkage(funcOp);
763e50a231dSLeandro Lupori   builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy,
764e50a231dSLeandro Lupori                       {loc, loc});
765e50a231dSLeandro Lupori   builder.setInsertionPointToStart(&funcOp.getRegion().back());
766e50a231dSLeandro Lupori   // generate body
767e50a231dSLeandro Lupori   fir::FortranVariableFlagsAttr attrs;
768e50a231dSLeandro Lupori   if (varAttrs != fir::FortranVariableFlagsEnum::None)
769e50a231dSLeandro Lupori     attrs = fir::FortranVariableFlagsAttr::get(builder.getContext(), varAttrs);
770e50a231dSLeandro Lupori   llvm::SmallVector<mlir::Value> typeparams;
771e50a231dSLeandro Lupori   if (typeInfo.getCharLength().has_value()) {
772e50a231dSLeandro Lupori     mlir::Value charLen = builder.createIntegerConstant(
773e50a231dSLeandro Lupori         loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
774e50a231dSLeandro Lupori     typeparams.push_back(charLen);
775e50a231dSLeandro Lupori   }
776e50a231dSLeandro Lupori   mlir::Value shape;
777e50a231dSLeandro Lupori   if (!typeInfo.isBox() && !typeInfo.getShape().empty()) {
778e50a231dSLeandro Lupori     llvm::SmallVector<mlir::Value> extents;
779e50a231dSLeandro Lupori     for (auto extent : typeInfo.getShape())
780e50a231dSLeandro Lupori       extents.push_back(
781e50a231dSLeandro Lupori           builder.createIntegerConstant(loc, builder.getIndexType(), extent));
782e50a231dSLeandro Lupori     shape = builder.create<fir::ShapeOp>(loc, extents);
783e50a231dSLeandro Lupori   }
7841710c8cfSSlava Zakharin   auto declDst = builder.create<hlfir::DeclareOp>(
7851710c8cfSSlava Zakharin       loc, funcOp.getArgument(0), copyFuncName + "_dst", shape, typeparams,
7861710c8cfSSlava Zakharin       /*dummy_scope=*/nullptr, attrs);
7871710c8cfSSlava Zakharin   auto declSrc = builder.create<hlfir::DeclareOp>(
7881710c8cfSSlava Zakharin       loc, funcOp.getArgument(1), copyFuncName + "_src", shape, typeparams,
7891710c8cfSSlava Zakharin       /*dummy_scope=*/nullptr, attrs);
790952bdaafSLeandro Lupori   converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs);
791e50a231dSLeandro Lupori   builder.create<mlir::func::ReturnOp>(loc);
792e50a231dSLeandro Lupori   return funcOp;
793e50a231dSLeandro Lupori }
794e50a231dSLeandro Lupori 
79578eac466SSergio Afonso bool ClauseProcessor::processCopyprivate(
796e50a231dSLeandro Lupori     mlir::Location currentLocation,
79778eac466SSergio Afonso     mlir::omp::CopyprivateClauseOps &result) const {
7987a66e420SKrzysztof Parzyszek   auto addCopyPrivateVar = [&](semantics::Symbol *sym) {
799e50a231dSLeandro Lupori     mlir::Value symVal = converter.getSymbolAddress(*sym);
800e50a231dSLeandro Lupori     auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>();
801e50a231dSLeandro Lupori     if (!declOp)
802e50a231dSLeandro Lupori       fir::emitFatalError(currentLocation,
803e50a231dSLeandro Lupori                           "COPYPRIVATE is supported only in HLFIR mode");
804e50a231dSLeandro Lupori     symVal = declOp.getBase();
805e50a231dSLeandro Lupori     mlir::Type symType = symVal.getType();
806e50a231dSLeandro Lupori     fir::FortranVariableFlagsEnum attrs =
807e50a231dSLeandro Lupori         declOp.getFortranAttrs().has_value()
808e50a231dSLeandro Lupori             ? *declOp.getFortranAttrs()
809e50a231dSLeandro Lupori             : fir::FortranVariableFlagsEnum::None;
810e50a231dSLeandro Lupori     mlir::Value cpVar = symVal;
811e50a231dSLeandro Lupori 
812e50a231dSLeandro Lupori     // CopyPrivate variables must be passed by reference. However, in the case
813e50a231dSLeandro Lupori     // of assumed shapes/vla the type is not a !fir.ref, but a !fir.box.
814e50a231dSLeandro Lupori     // In these cases to retrieve the appropriate !fir.ref<!fir.box<...>> to
815e50a231dSLeandro Lupori     // access the data we need we must perform an alloca and then store to it
816e50a231dSLeandro Lupori     // and retrieve the data from the new alloca.
817e50a231dSLeandro Lupori     if (mlir::isa<fir::BaseBoxType>(symType)) {
818e50a231dSLeandro Lupori       fir::FirOpBuilder &builder = converter.getFirOpBuilder();
819e50a231dSLeandro Lupori       auto alloca = builder.create<fir::AllocaOp>(currentLocation, symType);
820e50a231dSLeandro Lupori       builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
821e50a231dSLeandro Lupori       cpVar = alloca;
822e50a231dSLeandro Lupori     }
823e50a231dSLeandro Lupori 
82478eac466SSergio Afonso     result.copyprivateVars.push_back(cpVar);
825e50a231dSLeandro Lupori     mlir::func::FuncOp funcOp =
826e50a231dSLeandro Lupori         createCopyFunc(currentLocation, converter, cpVar.getType(), attrs);
827fdfeea5bSSergio Afonso     result.copyprivateSyms.push_back(mlir::SymbolRefAttr::get(funcOp));
828e50a231dSLeandro Lupori   };
829e50a231dSLeandro Lupori 
83063e70c05SKrzysztof Parzyszek   bool hasCopyPrivate = findRepeatableClause<clause::Copyprivate>(
8317a66e420SKrzysztof Parzyszek       [&](const clause::Copyprivate &clause, const parser::CharBlock &) {
83263e70c05SKrzysztof Parzyszek         for (const Object &object : clause.v) {
8338b18f2feSKrzysztof Parzyszek           semantics::Symbol *sym = object.sym();
834e50a231dSLeandro Lupori           if (const auto *commonDetails =
8357a66e420SKrzysztof Parzyszek                   sym->detailsIf<semantics::CommonBlockDetails>()) {
836e50a231dSLeandro Lupori             for (const auto &mem : commonDetails->objects())
837e50a231dSLeandro Lupori               addCopyPrivateVar(&*mem);
838e50a231dSLeandro Lupori             break;
839e50a231dSLeandro Lupori           }
840e50a231dSLeandro Lupori           addCopyPrivateVar(sym);
841e50a231dSLeandro Lupori         }
842e50a231dSLeandro Lupori       });
843e50a231dSLeandro Lupori 
844e50a231dSLeandro Lupori   return hasCopyPrivate;
845e50a231dSLeandro Lupori }
846e50a231dSLeandro Lupori 
84778eac466SSergio Afonso bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const {
848d48c849eSKrzysztof Parzyszek   auto process = [&](const omp::clause::Depend &clause,
849d48c849eSKrzysztof Parzyszek                      const parser::CharBlock &) {
850148a5579SKrzysztof Parzyszek     using Depend = omp::clause::Depend;
851f87737f3SKrzysztof Parzyszek     if (!std::holds_alternative<Depend::TaskDep>(clause.u)) {
852d48c849eSKrzysztof Parzyszek       TODO(converter.getCurrentLocation(),
853d48c849eSKrzysztof Parzyszek            "DEPEND clause with SINK or SOURCE is not supported yet");
854d48c849eSKrzysztof Parzyszek     }
855f87737f3SKrzysztof Parzyszek     auto &taskDep = std::get<Depend::TaskDep>(clause.u);
856f87737f3SKrzysztof Parzyszek     auto depType = std::get<clause::DependenceType>(taskDep.t);
857f87737f3SKrzysztof Parzyszek     auto &objects = std::get<omp::ObjectList>(taskDep.t);
85863e70c05SKrzysztof Parzyszek 
859f87737f3SKrzysztof Parzyszek     if (std::get<std::optional<omp::clause::Iterator>>(taskDep.t)) {
860d48c849eSKrzysztof Parzyszek       TODO(converter.getCurrentLocation(),
861d48c849eSKrzysztof Parzyszek            "Support for iterator modifiers is not implemented yet");
862d48c849eSKrzysztof Parzyszek     }
8634d4af15cSKareem Ergawy     mlir::omp::ClauseTaskDependAttr dependTypeOperand =
864f87737f3SKrzysztof Parzyszek         genDependKindAttr(converter, depType);
865fdfeea5bSSergio Afonso     result.dependKinds.append(objects.size(), dependTypeOperand);
86663e70c05SKrzysztof Parzyszek 
86763e70c05SKrzysztof Parzyszek     for (const omp::Object &object : objects) {
86863e70c05SKrzysztof Parzyszek       assert(object.ref() && "Expecting designator");
86963e70c05SKrzysztof Parzyszek 
8707a66e420SKrzysztof Parzyszek       if (evaluate::ExtractSubstring(*object.ref())) {
87163e70c05SKrzysztof Parzyszek         TODO(converter.getCurrentLocation(),
87263e70c05SKrzysztof Parzyszek              "substring not supported for task depend");
8737a66e420SKrzysztof Parzyszek       } else if (evaluate::IsArrayElement(*object.ref())) {
8744d4af15cSKareem Ergawy         TODO(converter.getCurrentLocation(),
8754d4af15cSKareem Ergawy              "array sections not supported for task depend");
8764d4af15cSKareem Ergawy       }
87763e70c05SKrzysztof Parzyszek 
8788b18f2feSKrzysztof Parzyszek       semantics::Symbol *sym = object.sym();
8794d4af15cSKareem Ergawy       const mlir::Value variable = converter.getSymbolAddress(*sym);
88078eac466SSergio Afonso       result.dependVars.push_back(variable);
8814d4af15cSKareem Ergawy     }
882d48c849eSKrzysztof Parzyszek   };
883d48c849eSKrzysztof Parzyszek 
884d48c849eSKrzysztof Parzyszek   return findRepeatableClause<omp::clause::Depend>(process);
8854d4af15cSKareem Ergawy }
8864d4af15cSKareem Ergawy 
887298ea9bfSRaghu Maddhipatla bool ClauseProcessor::processHasDeviceAddr(
88878eac466SSergio Afonso     mlir::omp::HasDeviceAddrClauseOps &result,
88988478a89SSergio Afonso     llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const {
890298ea9bfSRaghu Maddhipatla   return findRepeatableClause<omp::clause::HasDeviceAddr>(
891298ea9bfSRaghu Maddhipatla       [&](const omp::clause::HasDeviceAddr &devAddrClause,
8927a66e420SKrzysztof Parzyszek           const parser::CharBlock &) {
89378eac466SSergio Afonso         addUseDeviceClause(converter, devAddrClause.v, result.hasDeviceAddrVars,
89488478a89SSergio Afonso                            isDeviceSyms);
895298ea9bfSRaghu Maddhipatla       });
896298ea9bfSRaghu Maddhipatla }
897298ea9bfSRaghu Maddhipatla 
8984d4af15cSKareem Ergawy bool ClauseProcessor::processIf(
89963e70c05SKrzysztof Parzyszek     omp::clause::If::DirectiveNameModifier directiveName,
90078eac466SSergio Afonso     mlir::omp::IfClauseOps &result) const {
9014d4af15cSKareem Ergawy   bool found = false;
9027a66e420SKrzysztof Parzyszek   findRepeatableClause<omp::clause::If>([&](const omp::clause::If &clause,
9037a66e420SKrzysztof Parzyszek                                             const parser::CharBlock &source) {
9044d4af15cSKareem Ergawy     mlir::Location clauseLocation = converter.genLocation(source);
9057a66e420SKrzysztof Parzyszek     mlir::Value operand =
9067a66e420SKrzysztof Parzyszek         getIfClauseOperand(converter, clause, directiveName, clauseLocation);
9074d4af15cSKareem Ergawy     // Assume that, at most, a single 'if' clause will be applicable to the
9084d4af15cSKareem Ergawy     // given directive.
9094d4af15cSKareem Ergawy     if (operand) {
9102f3d0619SSergio Afonso       result.ifExpr = operand;
9114d4af15cSKareem Ergawy       found = true;
9124d4af15cSKareem Ergawy     }
9134d4af15cSKareem Ergawy   });
9144d4af15cSKareem Ergawy   return found;
9154d4af15cSKareem Ergawy }
9164d4af15cSKareem Ergawy 
917298ea9bfSRaghu Maddhipatla bool ClauseProcessor::processIsDevicePtr(
91878eac466SSergio Afonso     mlir::omp::IsDevicePtrClauseOps &result,
91988478a89SSergio Afonso     llvm::SmallVectorImpl<const semantics::Symbol *> &isDeviceSyms) const {
920298ea9bfSRaghu Maddhipatla   return findRepeatableClause<omp::clause::IsDevicePtr>(
921298ea9bfSRaghu Maddhipatla       [&](const omp::clause::IsDevicePtr &devPtrClause,
9227a66e420SKrzysztof Parzyszek           const parser::CharBlock &) {
92378eac466SSergio Afonso         addUseDeviceClause(converter, devPtrClause.v, result.isDevicePtrVars,
92488478a89SSergio Afonso                            isDeviceSyms);
925298ea9bfSRaghu Maddhipatla       });
926298ea9bfSRaghu Maddhipatla }
927298ea9bfSRaghu Maddhipatla 
9284d4af15cSKareem Ergawy bool ClauseProcessor::processLink(
9294d4af15cSKareem Ergawy     llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const {
93063e70c05SKrzysztof Parzyszek   return findRepeatableClause<omp::clause::Link>(
9317a66e420SKrzysztof Parzyszek       [&](const omp::clause::Link &clause, const parser::CharBlock &) {
9324d4af15cSKareem Ergawy         // Case: declare target link(var1, var2)...
9334d4af15cSKareem Ergawy         gatherFuncAndVarSyms(
93463e70c05SKrzysztof Parzyszek             clause.v, mlir::omp::DeclareTargetCaptureClause::link, result);
9354d4af15cSKareem Ergawy       });
9364d4af15cSKareem Ergawy }
9374d4af15cSKareem Ergawy 
9389ba41031SAkash Banerjee void ClauseProcessor::processMapObjects(
9399ba41031SAkash Banerjee     lower::StatementContext &stmtCtx, mlir::Location clauseLocation,
9409ba41031SAkash Banerjee     const omp::ObjectList &objects,
9419ba41031SAkash Banerjee     llvm::omp::OpenMPOffloadMappingFlags mapTypeBits,
942e508baccSagozillon     std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices,
9439ba41031SAkash Banerjee     llvm::SmallVectorImpl<mlir::Value> &mapVars,
94488478a89SSergio Afonso     llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms) const {
9459ba41031SAkash Banerjee   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
946e508baccSagozillon 
9479ba41031SAkash Banerjee   for (const omp::Object &object : objects) {
9489ba41031SAkash Banerjee     llvm::SmallVector<mlir::Value> bounds;
9499ba41031SAkash Banerjee     std::stringstream asFortran;
950e508baccSagozillon     std::optional<omp::Object> parentObj;
9519ba41031SAkash Banerjee 
952*662133a2SjeanPerier     fir::factory::AddrAndBoundsInfo info =
9539ba41031SAkash Banerjee         lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
9549ba41031SAkash Banerjee                                               mlir::omp::MapBoundsType>(
9559ba41031SAkash Banerjee             converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
9569ba41031SAkash Banerjee             object.ref(), clauseLocation, asFortran, bounds,
9579ba41031SAkash Banerjee             treatIndexAsSection);
9589ba41031SAkash Banerjee 
959e508baccSagozillon     mlir::Value baseOp = info.rawInput;
960e508baccSagozillon     if (object.sym()->owner().IsDerivedType()) {
961e508baccSagozillon       omp::ObjectList objectList = gatherObjectsOf(object, semaCtx);
962e508baccSagozillon       assert(!objectList.empty() &&
963e508baccSagozillon              "could not find parent objects of derived type member");
964e508baccSagozillon       parentObj = objectList[0];
965e508baccSagozillon       parentMemberIndices.emplace(parentObj.value(),
966e508baccSagozillon                                   OmpMapParentAndMemberData{});
967e508baccSagozillon 
968e508baccSagozillon       if (isMemberOrParentAllocatableOrPointer(object, semaCtx)) {
969e508baccSagozillon         llvm::SmallVector<int64_t> indices;
970e508baccSagozillon         generateMemberPlacementIndices(object, indices, semaCtx);
971e508baccSagozillon         baseOp = createParentSymAndGenIntermediateMaps(
972e508baccSagozillon             clauseLocation, converter, semaCtx, stmtCtx, objectList, indices,
973e508baccSagozillon             parentMemberIndices[parentObj.value()], asFortran.str(),
974e508baccSagozillon             mapTypeBits);
975e508baccSagozillon       }
976e508baccSagozillon     }
977e508baccSagozillon 
9789ba41031SAkash Banerjee     // Explicit map captures are captured ByRef by default,
9799ba41031SAkash Banerjee     // optimisation passes may alter this to ByCopy or other capture
9809ba41031SAkash Banerjee     // types to optimise
9819ba41031SAkash Banerjee     auto location = mlir::NameLoc::get(
9829ba41031SAkash Banerjee         mlir::StringAttr::get(firOpBuilder.getContext(), asFortran.str()),
9839ba41031SAkash Banerjee         baseOp.getLoc());
9849ba41031SAkash Banerjee     mlir::omp::MapInfoOp mapOp = createMapInfoOp(
9859ba41031SAkash Banerjee         firOpBuilder, location, baseOp,
9869ba41031SAkash Banerjee         /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds,
987e508baccSagozillon         /*members=*/{}, /*membersIndex=*/mlir::ArrayAttr{},
9889ba41031SAkash Banerjee         static_cast<
9899ba41031SAkash Banerjee             std::underlying_type_t<llvm::omp::OpenMPOffloadMappingFlags>>(
9909ba41031SAkash Banerjee             mapTypeBits),
9919ba41031SAkash Banerjee         mlir::omp::VariableCaptureKind::ByRef, baseOp.getType());
9929ba41031SAkash Banerjee 
993e508baccSagozillon     if (parentObj.has_value()) {
994e508baccSagozillon       parentMemberIndices[parentObj.value()].addChildIndexAndMapToParent(
995e508baccSagozillon           object, mapOp, semaCtx);
9969ba41031SAkash Banerjee     } else {
9979ba41031SAkash Banerjee       mapVars.push_back(mapOp);
99888478a89SSergio Afonso       mapSyms.push_back(object.sym());
9999ba41031SAkash Banerjee     }
10009ba41031SAkash Banerjee   }
10019ba41031SAkash Banerjee }
10029ba41031SAkash Banerjee 
10034d4af15cSKareem Ergawy bool ClauseProcessor::processMap(
10047a66e420SKrzysztof Parzyszek     mlir::Location currentLocation, lower::StatementContext &stmtCtx,
10054dd5180aSSergio Afonso     mlir::omp::MapClauseOps &result,
100688478a89SSergio Afonso     llvm::SmallVectorImpl<const semantics::Symbol *> *mapSyms) const {
1007435e850bSAndrew Gozillon   // We always require tracking of symbols, even if the caller does not,
1008435e850bSAndrew Gozillon   // so we create an optionally used local set of symbols when the mapSyms
1009435e850bSAndrew Gozillon   // argument is not present.
10107a66e420SKrzysztof Parzyszek   llvm::SmallVector<const semantics::Symbol *> localMapSyms;
10117a66e420SKrzysztof Parzyszek   llvm::SmallVectorImpl<const semantics::Symbol *> *ptrMapSyms =
1012435e850bSAndrew Gozillon       mapSyms ? mapSyms : &localMapSyms;
1013e508baccSagozillon   std::map<Object, OmpMapParentAndMemberData> parentMemberIndices;
1014435e850bSAndrew Gozillon 
1015973fa983SKrzysztof Parzyszek   auto process = [&](const omp::clause::Map &clause,
1016973fa983SKrzysztof Parzyszek                      const parser::CharBlock &source) {
101784115494SKrzysztof Parzyszek     using Map = omp::clause::Map;
10184d4af15cSKareem Ergawy     mlir::Location clauseLocation = converter.genLocation(source);
101952755ac2SKrzysztof Parzyszek     const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t;
10204d4af15cSKareem Ergawy     llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
10214d4af15cSKareem Ergawy         llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
10224d4af15cSKareem Ergawy     // If the map type is specified, then process it else Tofrom is the
10234d4af15cSKareem Ergawy     // default.
1024697d65deSKrzysztof Parzyszek     Map::MapType type = mapType.value_or(Map::MapType::Tofrom);
1025697d65deSKrzysztof Parzyszek     switch (type) {
1026148a5579SKrzysztof Parzyszek     case Map::MapType::To:
10274d4af15cSKareem Ergawy       mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
10284d4af15cSKareem Ergawy       break;
1029148a5579SKrzysztof Parzyszek     case Map::MapType::From:
10304d4af15cSKareem Ergawy       mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
10314d4af15cSKareem Ergawy       break;
1032148a5579SKrzysztof Parzyszek     case Map::MapType::Tofrom:
10334d4af15cSKareem Ergawy       mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
10344d4af15cSKareem Ergawy                      llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
10354d4af15cSKareem Ergawy       break;
1036148a5579SKrzysztof Parzyszek     case Map::MapType::Alloc:
1037148a5579SKrzysztof Parzyszek     case Map::MapType::Release:
10384d4af15cSKareem Ergawy       // alloc and release is the default map_type for the Target Data
10394d4af15cSKareem Ergawy       // Ops, i.e. if no bits for map_type is supplied then alloc/release
10404d4af15cSKareem Ergawy       // is implicitly assumed based on the target directive. Default
10414d4af15cSKareem Ergawy       // value for Target Data and Enter Data is alloc and for Exit Data
10424d4af15cSKareem Ergawy       // it is release.
10434d4af15cSKareem Ergawy       break;
1044148a5579SKrzysztof Parzyszek     case Map::MapType::Delete:
10454d4af15cSKareem Ergawy       mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
10464d4af15cSKareem Ergawy     }
10474d4af15cSKareem Ergawy 
104852755ac2SKrzysztof Parzyszek     if (typeMods) {
104952755ac2SKrzysztof Parzyszek       if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Always))
1050697d65deSKrzysztof Parzyszek         mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
1051697d65deSKrzysztof Parzyszek       // Diagnose unimplemented map-type-modifiers.
105252755ac2SKrzysztof Parzyszek       if (llvm::any_of(*typeMods, [](Map::MapTypeModifier m) {
1053697d65deSKrzysztof Parzyszek             return m != Map::MapTypeModifier::Always;
1054697d65deSKrzysztof Parzyszek           })) {
1055697d65deSKrzysztof Parzyszek         TODO(currentLocation, "Map type modifiers (other than 'ALWAYS')"
1056697d65deSKrzysztof Parzyszek                               " are not implemented yet");
1057148a5579SKrzysztof Parzyszek       }
10584d4af15cSKareem Ergawy     }
1059973fa983SKrzysztof Parzyszek 
106052755ac2SKrzysztof Parzyszek     if (iterator) {
1061973fa983SKrzysztof Parzyszek       TODO(currentLocation,
1062973fa983SKrzysztof Parzyszek            "Support for iterator modifiers is not implemented yet");
1063973fa983SKrzysztof Parzyszek     }
106452755ac2SKrzysztof Parzyszek     if (mappers) {
106552755ac2SKrzysztof Parzyszek       TODO(currentLocation,
106652755ac2SKrzysztof Parzyszek            "Support for mapper modifiers is not implemented yet");
106752755ac2SKrzysztof Parzyszek     }
1068973fa983SKrzysztof Parzyszek 
10699ba41031SAkash Banerjee     processMapObjects(stmtCtx, clauseLocation,
10709ba41031SAkash Banerjee                       std::get<omp::ObjectList>(clause.t), mapTypeBits,
107188478a89SSergio Afonso                       parentMemberIndices, result.mapVars, *ptrMapSyms);
1072973fa983SKrzysztof Parzyszek   };
1073435e850bSAndrew Gozillon 
1074973fa983SKrzysztof Parzyszek   bool clauseFound = findRepeatableClause<omp::clause::Map>(process);
1075e508baccSagozillon   insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices,
1076e508baccSagozillon                                result.mapVars, *ptrMapSyms);
1077435e850bSAndrew Gozillon 
1078435e850bSAndrew Gozillon   return clauseFound;
10794d4af15cSKareem Ergawy }
10804d4af15cSKareem Ergawy 
1081b54be00aSSergio Afonso bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
1082b54be00aSSergio Afonso                                            mlir::omp::MapClauseOps &result) {
1083e508baccSagozillon   std::map<Object, OmpMapParentAndMemberData> parentMemberIndices;
1084b54be00aSSergio Afonso   llvm::SmallVector<const semantics::Symbol *> mapSymbols;
1085b54be00aSSergio Afonso 
1086b54be00aSSergio Afonso   auto callbackFn = [&](const auto &clause, const parser::CharBlock &source) {
1087b54be00aSSergio Afonso     mlir::Location clauseLocation = converter.genLocation(source);
10881c6ec29bSKrzysztof Parzyszek     const auto &[expectation, mapper, iterator, objects] = clause.t;
1089b54be00aSSergio Afonso     // TODO Support motion modifiers: present, mapper, iterator.
10901c6ec29bSKrzysztof Parzyszek     if (expectation) {
10911c6ec29bSKrzysztof Parzyszek       TODO(clauseLocation, "PRESENT modifier is not supported yet");
10921c6ec29bSKrzysztof Parzyszek     } else if (mapper) {
10931c6ec29bSKrzysztof Parzyszek       TODO(clauseLocation, "Mapper modifier is not supported yet");
10941c6ec29bSKrzysztof Parzyszek     } else if (iterator) {
10951c6ec29bSKrzysztof Parzyszek       TODO(clauseLocation, "Iterator modifier is not supported yet");
10961c6ec29bSKrzysztof Parzyszek     }
1097b54be00aSSergio Afonso     constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1098b54be00aSSergio Afonso         std::is_same_v<llvm::remove_cvref_t<decltype(clause)>, omp::clause::To>
1099b54be00aSSergio Afonso             ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
1100b54be00aSSergio Afonso             : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1101b54be00aSSergio Afonso 
11021c6ec29bSKrzysztof Parzyszek     processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
11031c6ec29bSKrzysztof Parzyszek                       parentMemberIndices, result.mapVars, mapSymbols);
1104b54be00aSSergio Afonso   };
1105b54be00aSSergio Afonso 
1106b54be00aSSergio Afonso   bool clauseFound = findRepeatableClause<omp::clause::To>(callbackFn);
1107b54be00aSSergio Afonso   clauseFound =
1108b54be00aSSergio Afonso       findRepeatableClause<omp::clause::From>(callbackFn) || clauseFound;
1109b54be00aSSergio Afonso 
1110e508baccSagozillon   insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices,
1111e508baccSagozillon                                result.mapVars, mapSymbols);
1112e508baccSagozillon 
1113b54be00aSSergio Afonso   return clauseFound;
1114b54be00aSSergio Afonso }
1115b54be00aSSergio Afonso 
111670ef5eb6Sharishch4 bool ClauseProcessor::processNontemporal(
111770ef5eb6Sharishch4     mlir::omp::NontemporalClauseOps &result) const {
111870ef5eb6Sharishch4   return findRepeatableClause<omp::clause::Nontemporal>(
111970ef5eb6Sharishch4       [&](const omp::clause::Nontemporal &clause, const parser::CharBlock &) {
112070ef5eb6Sharishch4         for (const Object &object : clause.v) {
112170ef5eb6Sharishch4           semantics::Symbol *sym = object.sym();
112270ef5eb6Sharishch4           mlir::Value symVal = converter.getSymbolAddress(*sym);
112370ef5eb6Sharishch4           result.nontemporalVars.push_back(symVal);
112470ef5eb6Sharishch4         }
112570ef5eb6Sharishch4       });
112670ef5eb6Sharishch4 }
112770ef5eb6Sharishch4 
11284d4af15cSKareem Ergawy bool ClauseProcessor::processReduction(
112978eac466SSergio Afonso     mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result,
113088478a89SSergio Afonso     llvm::SmallVectorImpl<const semantics::Symbol *> &outReductionSyms) const {
113163e70c05SKrzysztof Parzyszek   return findRepeatableClause<omp::clause::Reduction>(
11327a66e420SKrzysztof Parzyszek       [&](const omp::clause::Reduction &clause, const parser::CharBlock &) {
113373402634SSergio Afonso         llvm::SmallVector<mlir::Value> reductionVars;
113474a87548STom Eccles         llvm::SmallVector<bool> reduceVarByRef;
113573402634SSergio Afonso         llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
11367a66e420SKrzysztof Parzyszek         llvm::SmallVector<const semantics::Symbol *> reductionSyms;
11374d4af15cSKareem Ergawy         ReductionProcessor rp;
113888478a89SSergio Afonso         rp.addDeclareReduction(currentLocation, converter, clause,
113988478a89SSergio Afonso                                reductionVars, reduceVarByRef,
114088478a89SSergio Afonso                                reductionDeclSymbols, reductionSyms);
114173402634SSergio Afonso 
114273402634SSergio Afonso         // Copy local lists into the output.
114378eac466SSergio Afonso         llvm::copy(reductionVars, std::back_inserter(result.reductionVars));
1144fdfeea5bSSergio Afonso         llvm::copy(reduceVarByRef, std::back_inserter(result.reductionByref));
114573402634SSergio Afonso         llvm::copy(reductionDeclSymbols,
1146fdfeea5bSSergio Afonso                    std::back_inserter(result.reductionSyms));
114788478a89SSergio Afonso         llvm::copy(reductionSyms, std::back_inserter(outReductionSyms));
11484d4af15cSKareem Ergawy       });
11494d4af15cSKareem Ergawy }
11504d4af15cSKareem Ergawy 
11514d4af15cSKareem Ergawy bool ClauseProcessor::processTo(
11524d4af15cSKareem Ergawy     llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const {
115363e70c05SKrzysztof Parzyszek   return findRepeatableClause<omp::clause::To>(
11547a66e420SKrzysztof Parzyszek       [&](const omp::clause::To &clause, const parser::CharBlock &) {
11554d4af15cSKareem Ergawy         // Case: declare target to(func, var1, var2)...
1156148a5579SKrzysztof Parzyszek         gatherFuncAndVarSyms(std::get<ObjectList>(clause.t),
11574d4af15cSKareem Ergawy                              mlir::omp::DeclareTargetCaptureClause::to, result);
11584d4af15cSKareem Ergawy       });
11594d4af15cSKareem Ergawy }
11604d4af15cSKareem Ergawy 
11614d4af15cSKareem Ergawy bool ClauseProcessor::processEnter(
11624d4af15cSKareem Ergawy     llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const {
116363e70c05SKrzysztof Parzyszek   return findRepeatableClause<omp::clause::Enter>(
11647a66e420SKrzysztof Parzyszek       [&](const omp::clause::Enter &clause, const parser::CharBlock &) {
11654d4af15cSKareem Ergawy         // Case: declare target enter(func, var1, var2)...
116663e70c05SKrzysztof Parzyszek         gatherFuncAndVarSyms(
116763e70c05SKrzysztof Parzyszek             clause.v, mlir::omp::DeclareTargetCaptureClause::enter, result);
11684d4af15cSKareem Ergawy       });
11694d4af15cSKareem Ergawy }
11704d4af15cSKareem Ergawy 
11714d4af15cSKareem Ergawy bool ClauseProcessor::processUseDeviceAddr(
11729ba41031SAkash Banerjee     lower::StatementContext &stmtCtx, mlir::omp::UseDeviceAddrClauseOps &result,
11737a66e420SKrzysztof Parzyszek     llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const {
1174e508baccSagozillon   std::map<Object, OmpMapParentAndMemberData> parentMemberIndices;
11759ba41031SAkash Banerjee   bool clauseFound = findRepeatableClause<omp::clause::UseDeviceAddr>(
11769ba41031SAkash Banerjee       [&](const omp::clause::UseDeviceAddr &clause,
11779ba41031SAkash Banerjee           const parser::CharBlock &source) {
11789ba41031SAkash Banerjee         mlir::Location location = converter.genLocation(source);
11799ba41031SAkash Banerjee         llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
11809ba41031SAkash Banerjee             llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
11819ba41031SAkash Banerjee             llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
11829ba41031SAkash Banerjee         processMapObjects(stmtCtx, location, clause.v, mapTypeBits,
11839ba41031SAkash Banerjee                           parentMemberIndices, result.useDeviceAddrVars,
118488478a89SSergio Afonso                           useDeviceSyms);
11854d4af15cSKareem Ergawy       });
11869ba41031SAkash Banerjee 
1187e508baccSagozillon   insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices,
118888478a89SSergio Afonso                                result.useDeviceAddrVars, useDeviceSyms);
11899ba41031SAkash Banerjee   return clauseFound;
11904d4af15cSKareem Ergawy }
11914d4af15cSKareem Ergawy 
11924d4af15cSKareem Ergawy bool ClauseProcessor::processUseDevicePtr(
11939ba41031SAkash Banerjee     lower::StatementContext &stmtCtx, mlir::omp::UseDevicePtrClauseOps &result,
11947a66e420SKrzysztof Parzyszek     llvm::SmallVectorImpl<const semantics::Symbol *> &useDeviceSyms) const {
1195e508baccSagozillon   std::map<Object, OmpMapParentAndMemberData> parentMemberIndices;
1196e508baccSagozillon 
11979ba41031SAkash Banerjee   bool clauseFound = findRepeatableClause<omp::clause::UseDevicePtr>(
11989ba41031SAkash Banerjee       [&](const omp::clause::UseDevicePtr &clause,
11999ba41031SAkash Banerjee           const parser::CharBlock &source) {
12009ba41031SAkash Banerjee         mlir::Location location = converter.genLocation(source);
12019ba41031SAkash Banerjee         llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
12029ba41031SAkash Banerjee             llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
12039ba41031SAkash Banerjee             llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
12049ba41031SAkash Banerjee         processMapObjects(stmtCtx, location, clause.v, mapTypeBits,
12059ba41031SAkash Banerjee                           parentMemberIndices, result.useDevicePtrVars,
120688478a89SSergio Afonso                           useDeviceSyms);
12074d4af15cSKareem Ergawy       });
12089ba41031SAkash Banerjee 
1209e508baccSagozillon   insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices,
121088478a89SSergio Afonso                                result.useDevicePtrVars, useDeviceSyms);
12119ba41031SAkash Banerjee   return clauseFound;
12124d4af15cSKareem Ergawy }
1213298ea9bfSRaghu Maddhipatla 
12144d4af15cSKareem Ergawy } // namespace omp
12154d4af15cSKareem Ergawy } // namespace lower
12164d4af15cSKareem Ergawy } // namespace Fortran
1217