llvm/flang/lib/parser/openmp-grammar.h
2018-06-01 11:15:32 -07:00

356 lines
18 KiB
C++

// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef OPENMP_PARSER_GRAMMAR_H_
#define OPENMP_PARSER_GRAMMAR_H_
// Top-level grammar specification for Fortran. These parsers drive
// the tokenization parsers in cooked-tokens.h to consume characters,
// recognize the productions of Fortran, and to construct a parse tree.
// See ParserCombinators.md for documentation on the parser combinator
// library used here to implement an LL recursive descent recognizer.
#include "basic-parsers.h"
#include "characters.h"
#include "debug-parser.h"
#include "grammar.h"
#include "parse-tree.h"
#include "stmt-parser.h"
#include "token-parsers.h"
#include "type-parsers.h"
#include "user-state.h"
#include <cinttypes>
#include <cstdio>
#include <functional>
#include <list>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
// OpenMP Directives and Clauses
namespace Fortran::parser {
constexpr auto beginOmpDirective = skipEmptyLines >> space >> "!$OMP "_sptok;
// OpenMP Clauses
// DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE )
TYPE_PARSER(construct<OmpDefaultClause>(
"PRIVATE" >> pure(OmpDefaultClause::Type::Private) ||
"FIRSTPRIVATE" >> pure(OmpDefaultClause::Type::Firstprivate) ||
"SHARED" >> pure(OmpDefaultClause::Type::Shared) ||
"NONE" >> pure(OmpDefaultClause::Type::None)))
// PROC_BIND(CLOSE | MASTER | SPREAD)
TYPE_PARSER(construct<OmpProcBindClause>(
"CLOSE" >> pure(OmpProcBindClause::Type::Close) ||
"MASTER" >> pure(OmpProcBindClause::Type::Master) ||
"SPREAD" >> pure(OmpProcBindClause::Type::Spread)))
// MAP ([ [map-type-modifier[,]] map-type : ] list)
// map-type-modifier -> ALWAYS
// map-type -> TO | FROM | TOFROM | ALLOC | RELEASE | DELETE
TYPE_PARSER(construct<OmpMapClause>(
maybe(maybe("ALWAYS"_tok >> maybe(","_ch)) >>
("TO" >> pure(OmpMapClause::Type::To) / ":"_ch ||
"FROM" >> pure(OmpMapClause::Type::From) / ":"_ch ||
"TOFROM" >> pure(OmpMapClause::Type::Tofrom) / ":"_ch ||
"ALLOC" >> pure(OmpMapClause::Type::Alloc) / ":"_ch ||
"RELEASE" >> pure(OmpMapClause::Type::Release) / ":"_ch ||
"DELETE" >> pure(OmpMapClause::Type::Delete) / ":"_ch)),
nonemptyList(name)))
// SCHEDULE ([modifier [, modifier]:]kind[, chunk_size])
// Modifier -> MONITONIC | NONMONOTONIC | SIMD
// kind -> STATIC | DYNAMIC | GUIDED | AUTO | RUNTIME
// chunk_size -> ScalarIntExpr
TYPE_PARSER(construct<OmpScheduleModifierType>(
"MONOTONIC" >> pure(OmpScheduleModifierType::ModType::Monotonic) ||
"NONMONOTONIC" >> pure(OmpScheduleModifierType::ModType::Nonmonotonic) ||
"SIMD" >> pure(OmpScheduleModifierType::ModType::Simd)))
TYPE_PARSER(construct<OmpScheduleModifier>(Parser<OmpScheduleModifierType>{},
maybe(","_ch >> Parser<OmpScheduleModifierType>{})))
TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
"STATIC" >> pure(OmpScheduleClause::ScheduleType::Static) ||
"DYNAMIC" >> pure(OmpScheduleClause::ScheduleType::Dynamic) ||
"GUIDED" >> pure(OmpScheduleClause::ScheduleType::Guided) ||
"AUTO" >> pure(OmpScheduleClause::ScheduleType::Auto) ||
"RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
maybe(","_ch) >> scalarIntExpr))
// IF(directive-name-modifier: scalar-logical-expr)
TYPE_PARSER(construct<OmpIfClause>(
("PARALLEL"_tok >> pure(OmpIfClause::DirectiveNameModifier::Parallel) ||
"TARGET ENTER DATA"_tok >>
pure(OmpIfClause::DirectiveNameModifier::TargetEnterData) ||
"TARGET EXIT DATA"_tok >>
pure(OmpIfClause::DirectiveNameModifier::TargetExitData) ||
"TARGET DATA"_tok >>
pure(OmpIfClause::DirectiveNameModifier::TargetData) ||
"TARGET UPDATE"_tok >>
pure(OmpIfClause::DirectiveNameModifier::TargetUpdate) ||
"TARGET"_tok >> pure(OmpIfClause::DirectiveNameModifier::Target) ||
"TASKLOOP"_tok >> pure(OmpIfClause::DirectiveNameModifier::Taskloop) ||
"TASK"_tok >> pure(OmpIfClause::DirectiveNameModifier::Task)) /
maybe(":"_ch),
scalarLogicalExpr))
// REDUCTION(reduction-identifier: list)
constexpr auto reductionBinaryOperator = "+" >>
pure(OmpReductionOperator::BinaryOperator::Add) ||
"-" >> pure(OmpReductionOperator::BinaryOperator::Subtract) ||
"*" >> pure(OmpReductionOperator::BinaryOperator::Multiply) ||
".AND." >> pure(OmpReductionOperator::BinaryOperator::AND) ||
".OR." >> pure(OmpReductionOperator::BinaryOperator::OR) ||
".EQV." >> pure(OmpReductionOperator::BinaryOperator::EQV) ||
".NEQV." >> pure(OmpReductionOperator::BinaryOperator::NEQV);
constexpr auto reductionProcedureOperator = "MIN" >>
pure(OmpReductionOperator::ProcedureOperator::MIN) ||
"MAX" >> pure(OmpReductionOperator::ProcedureOperator::MAX) ||
"IAND" >> pure(OmpReductionOperator::ProcedureOperator::IAND) ||
"IOR" >> pure(OmpReductionOperator::ProcedureOperator::IOR) ||
"IEOR" >> pure(OmpReductionOperator::ProcedureOperator::IEOR);
TYPE_PARSER(construct<OmpReductionOperator>(reductionBinaryOperator) ||
construct<OmpReductionOperator>(reductionProcedureOperator))
TYPE_PARSER(construct<OmpReductionClause>(
Parser<OmpReductionOperator>{} / ":"_ch, nonemptyList(designator)))
// DEPEND(SOURCE | SINK : vec | (IN | OUT | INOUT) : list
TYPE_PARSER(construct<OmpDependSinkVecLength>(
indirect(Parser<DefinedOperator>{}), scalarIntConstantExpr))
TYPE_PARSER(
construct<OmpDependSinkVec>(name, maybe(Parser<OmpDependSinkVecLength>{})))
TYPE_PARSER(construct<OmpDependenceType>(
"IN"_tok >> pure(OmpDependenceType::Type::In) ||
"OUT"_tok >> pure(OmpDependenceType::Type::Out) ||
"INOUT"_tok >> pure(OmpDependenceType::Type::Inout)))
TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US,
construct<OmpDependClause>(construct<OmpDependClause::Sink>(
"SINK"_tok >> ":"_ch >> nonemptyList(Parser<OmpDependSinkVec>{}))) ||
construct<OmpDependClause>(
construct<OmpDependClause::Source>("SOURCE"_tok)) ||
construct<OmpDependClause>(construct<OmpDependClause::InOut>(
Parser<OmpDependenceType>{}, ":"_ch >> nonemptyList(designator))))
// LINEAR(list: linear-step)
TYPE_PARSER(construct<OmpLinearModifier>(
"REF"_tok >> pure(OmpLinearModifier::Type::Ref) ||
"VAL"_tok >> pure(OmpLinearModifier::Type::Val) ||
"UVAL"_tok >> pure(OmpLinearModifier::Type::Uval)))
TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US,
construct<OmpLinearClause>(
construct<OmpLinearClause>(construct<OmpLinearClause::WithModifier>(
Parser<OmpLinearModifier>{}, parenthesized(nonemptyList(name)),
maybe(":"_ch >> scalarIntConstantExpr))) ||
construct<OmpLinearClause>(construct<OmpLinearClause::WithoutModifier>(
nonemptyList(name), maybe(":"_ch >> scalarIntConstantExpr)))))
// ALIGNED(list: alignment)
TYPE_PARSER(construct<OmpAlignedClause>(
nonemptyList(name), maybe(":"_ch) >> scalarIntConstantExpr))
TYPE_PARSER(construct<OmpNameList>(pure(OmpNameList::Kind::Object), name) ||
construct<OmpNameList>("/" >> pure(OmpNameList::Kind::Common), name / "/"))
TYPE_PARSER(
construct<OmpClause>(construct<OmpClause::Defaultmap>("DEFAULTMAP"_tok >>
parenthesized("TOFROM"_tok >> ":"_ch >> "SCALAR"_tok))) ||
construct<OmpClause>(construct<OmpClause::Inbranch>("INBRANCH"_tok)) ||
construct<OmpClause>(construct<OmpClause::Mergeable>("MERGEABLE"_tok)) ||
construct<OmpClause>(construct<OmpClause::Nogroup>("NOGROUP"_tok)) ||
construct<OmpClause>(
construct<OmpClause::Notinbranch>("NOTINBRANCH"_tok)) ||
construct<OmpClause>(construct<OmpClause::Nowait>("NOWAIT"_tok)) ||
construct<OmpClause>(construct<OmpClause::Untied>("UNTIED"_tok)) ||
construct<OmpClause>(construct<OmpClause::Collapse>(
"COLLAPSE"_tok >> parenthesized(scalarIntConstantExpr))) ||
construct<OmpClause>(construct<OmpClause::Copyin>(
"COPYIN"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::Copyprivate>("COPYPRIVATE"_tok >>
parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::Device>(
"DEVICE"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(
construct<OmpClause::DistSchedule>("DIST_SCHEDULE"_tok >>
parenthesized("STATIC"_tok >> ","_ch >> scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::Final>(
"FINAL"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(
construct<OmpClause::Firstprivate>("FIRSTPRIVATE"_tok >>
parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::From>(
"FROM"_tok >> parenthesized(nonemptyList(designator)))) ||
construct<OmpClause>(construct<OmpClause::Grainsize>(
"GRAINSIZE"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::Lastprivate>("LASTPRIVATE"_tok >>
parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::Link>(
"LINK"_tok >> parenthesized(nonemptyList(name)))) ||
construct<OmpClause>(construct<OmpClause::NumTasks>(
"NUM_TASKS"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::NumTeams>(
"NUM_TEAMS"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::NumThreads>(
"NUM_THREADS"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::Ordered>(
"ORDERED"_tok >> maybe(parenthesized(scalarIntConstantExpr)))) ||
construct<OmpClause>(construct<OmpClause::Priority>(
"PRIORITY"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::Private>(
"PRIVATE"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::Safelen>(
"SAFELEN"_tok >> parenthesized(scalarIntConstantExpr))) ||
construct<OmpClause>(construct<OmpClause::Shared>(
"SHARED"_tok >> parenthesized(nonemptyList(Parser<OmpNameList>{})))) ||
construct<OmpClause>(construct<OmpClause::Simdlen>(
"SIMDLEN"_tok >> parenthesized(scalarIntConstantExpr))) ||
construct<OmpClause>(construct<OmpClause::ThreadLimit>(
"THREAD_LIMIT"_tok >> parenthesized(scalarIntExpr))) ||
construct<OmpClause>(construct<OmpClause::To>(
"TO"_tok >> parenthesized(nonemptyList(designator)))) ||
construct<OmpClause>(construct<OmpClause::Uniform>(
"UNIFORM"_tok >> parenthesized(nonemptyList(name)))) ||
construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
"USE_DEVICE_PTR"_tok >> parenthesized(nonemptyList(name)))) ||
construct<OmpClause>(
"ALIGNED"_tok >> parenthesized(Parser<OmpAlignedClause>{})) ||
construct<OmpClause>(
"DEFAULT"_tok >> parenthesized(Parser<OmpDefaultClause>{})) ||
construct<OmpClause>(
"DEPEND"_tok >> parenthesized(Parser<OmpDependClause>{})) ||
construct<OmpClause>("IF"_tok >> parenthesized(Parser<OmpIfClause>{})) ||
construct<OmpClause>(
"LINEAR"_tok >> parenthesized(Parser<OmpLinearClause>{})) ||
construct<OmpClause>("MAP"_tok >> parenthesized(Parser<OmpMapClause>{})) ||
construct<OmpClause>(
"PROC_BIND"_tok >> parenthesized(Parser<OmpProcBindClause>{})) ||
construct<OmpClause>(
"REDUCTION"_tok >> parenthesized(Parser<OmpReductionClause>{})) ||
construct<OmpClause>(
"SCHEDULE"_tok >> parenthesized(Parser<OmpScheduleClause>{})))
TYPE_PARSER(skipEmptyLines >> space >> "!$OMP END"_sptok >>
(construct<OmpEndDirective>(Parser<OmpLoopDirective>{})))
// Omp directives enclosing do loop
TYPE_PARSER(
construct<OmpLoopDirective>(
construct<OmpLoopDirective::DistributeParallelDoSimd>(
"DISTRIBUTE PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::DistributeParallelDo>(
"DISTRIBUTE PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::DistributeSimd>(
"DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::Distribute>(
"DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::DoSimd>(
"DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::Do>(
"DO"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::ParallelDoSimd>(
"PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::ParallelDo>(
"PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::Simd>(
"SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TargetParallelDoSimd>(
"TARGET PARALLEL DO SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::TargetParallelDo>(
"TARGET PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::TargetSimd>(
"TARGET SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TargetTeamsDistributeParallelDoSimd>(
"TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >>
many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TargetTeamsDistributeParallelDo>(
"TARGET TEAMS DISTRIBUTE PARALLEL DO"_tok >>
many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TargetTeamsDistributeSimd>(
"TARGET TEAMS DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TargetTeamsDistribute>(
"TARGET TEAMS DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::TaskloopSimd>(
"TASKLOOP SIMD" >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::Taskloop>(
"TASKLOOP" >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TeamsDistributeParallelDoSimd>(
"TEAMS DISTRIBUTE PARALLEL DO SIMD"_tok >>
many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TeamsDistributeParallelDo>(
"TEAMS DISTRIBUTE PARALLEL DO"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(
construct<OmpLoopDirective::TeamsDistributeSimd>(
"TEAMS DISTRIBUTE SIMD"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpLoopDirective>(construct<OmpLoopDirective::TeamsDistribute>(
"TEAMS DISTRIBUTE"_tok >> many(Parser<OmpClause>{}))))
TYPE_PARSER(construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::Barrier>(
"BARRIER"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::CancellationPoint>(
"CANCELLATION POINT"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(construct<OmpStandaloneDirective::Cancel>(
"CANCEL"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(construct<OmpStandaloneDirective::Flush>(
"FLUSH"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::TargetEnterData>(
"TARGET ENTER DATA"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::TargetExitData>(
"TARGET EXIT DATA"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::TargetUpdate>(
"TARGET UPDATE"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::Taskwait>(
"TASKWAIT"_tok >> many(Parser<OmpClause>{}))) ||
construct<OmpStandaloneDirective>(
construct<OmpStandaloneDirective::Taskyield>(
"TASKYIELD"_tok >> many(Parser<OmpClause>{}))))
TYPE_PARSER(
construct<OpenMPLoopConstruct>(statement(Parser<OmpLoopDirective>{}),
Parser<DoConstruct>{}, maybe(Parser<OmpEndDirective>{})))
TYPE_PARSER(construct<OpenMPStandaloneConstruct>(
statement(Parser<OmpStandaloneDirective>{})))
TYPE_CONTEXT_PARSER("OpenMP construct"_en_US,
beginOmpDirective >> (construct<OpenMPConstruct>(
indirect(Parser<OpenMPStandaloneConstruct>{})) ||
construct<OpenMPConstruct>(
indirect(Parser<OpenMPLoopConstruct>{}))))
} // namespace Fortran::parser
#endif // OPENMP_PARSER_GRAMMAR_H_