//===-- lib/Parser/openacc-parsers.cpp ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Top-level grammar specification for OpenACC 3.3. #include "basic-parsers.h" #include "expr-parsers.h" #include "misc-parsers.h" #include "stmt-parser.h" #include "token-parsers.h" #include "type-parser-implementation.h" #include "flang/Parser/parse-tree.h" // OpenACC Directives and Clauses namespace Fortran::parser { constexpr auto startAccLine = skipStuffBeforeStatement >> ("!$ACC "_sptok || "C$ACC "_sptok || "*$ACC "_sptok); constexpr auto endAccLine = space >> endOfLine; // Autogenerated clauses parser. Information is taken from ACC.td and the // parser is generated by tablegen. // Scalar value parsers are provided by Flang directly. Specific value parsers // are provided below. #define GEN_FLANG_CLAUSES_PARSER #include "llvm/Frontend/OpenACC/ACC.inc" TYPE_PARSER( construct(designator) || construct("/" >> name / "/")) TYPE_PARSER(construct(nonemptyList(Parser{}))) TYPE_PARSER(construct( maybe(Parser{}), Parser{})) TYPE_PARSER(construct( Parser{} / ":", Parser{})) // 2.16 (3249) wait-argument is: // [devnum : int-expr :] [queues :] int-expr-list TYPE_PARSER(construct(maybe("DEVNUM:" >> scalarIntExpr / ":"), "QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr))) // 2.9 (1984-1986) size-expr is one of: // * (represented as an empty std::optional) // int-expr TYPE_PARSER(construct(scalarIntExpr) || construct("*" >> construct>())) TYPE_PARSER(construct(nonemptyList(Parser{}))) TYPE_PARSER(sourced(construct( first("*" >> pure(Fortran::common::OpenACCDeviceType::Star), "DEFAULT" >> pure(Fortran::common::OpenACCDeviceType::Default), "NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), "ACC_DEVICE_NVIDIA" >> pure(Fortran::common::OpenACCDeviceType::Nvidia), "RADEON" >> pure(Fortran::common::OpenACCDeviceType::Radeon), "HOST" >> pure(Fortran::common::OpenACCDeviceType::Host), "MULTICORE" >> pure(Fortran::common::OpenACCDeviceType::Multicore))))) TYPE_PARSER( construct(nonemptyList(Parser{}))) // tile size is one of: // * (represented as an empty std::optional) // constant-int-expr TYPE_PARSER(construct(scalarIntConstantExpr) || construct( "*" >> construct>())) TYPE_PARSER(construct(nonemptyList(Parser{}))) // 2.9 (1979-1982) gang-arg is one of : // [num:]int-expr // dim:int-expr // static:size-expr TYPE_PARSER(construct(construct( "STATIC: " >> Parser{})) || construct( construct("DIM: " >> scalarIntExpr)) || construct( construct(maybe("NUM: "_tok) >> scalarIntExpr))) // 2.9 gang-arg-list TYPE_PARSER( construct(many(maybe(","_tok) >> Parser{}))) // 2.9.1 collapse TYPE_PARSER(construct( "FORCE:"_tok >> pure(true) || pure(false), scalarIntConstantExpr)) // 2.5.15 Reduction // Operator for reduction TYPE_PARSER(sourced(construct( first("+" >> pure(AccReductionOperator::Operator::Plus), "*" >> pure(AccReductionOperator::Operator::Multiply), "MAX" >> pure(AccReductionOperator::Operator::Max), "MIN" >> pure(AccReductionOperator::Operator::Min), "IAND" >> pure(AccReductionOperator::Operator::Iand), "IOR" >> pure(AccReductionOperator::Operator::Ior), "IEOR" >> pure(AccReductionOperator::Operator::Ieor), ".AND." >> pure(AccReductionOperator::Operator::And), ".OR." >> pure(AccReductionOperator::Operator::Or), ".EQV." >> pure(AccReductionOperator::Operator::Eqv), ".NEQV." >> pure(AccReductionOperator::Operator::Neqv))))) // 2.15.1 Bind clause TYPE_PARSER(sourced(construct(name)) || sourced(construct(scalarDefaultCharExpr))) // 2.5.16 Default clause TYPE_PARSER(construct( first("NONE" >> pure(llvm::acc::DefaultValue::ACC_Default_none), "PRESENT" >> pure(llvm::acc::DefaultValue::ACC_Default_present)))) // SELF clause is either a simple optional condition for compute construct // or a synonym of the HOST clause for the update directive 2.14.4 holding // an object list. TYPE_PARSER(construct(Parser{}) || construct(scalarLogicalExpr)) // Modifier for copyin, copyout, cache and create TYPE_PARSER(construct( first("ZERO:" >> pure(AccDataModifier::Modifier::Zero), "READONLY:" >> pure(AccDataModifier::Modifier::ReadOnly)))) // Combined directives TYPE_PARSER(sourced(construct( first("KERNELS LOOP" >> pure(llvm::acc::Directive::ACCD_kernels_loop), "PARALLEL LOOP" >> pure(llvm::acc::Directive::ACCD_parallel_loop), "SERIAL LOOP" >> pure(llvm::acc::Directive::ACCD_serial_loop))))) // Block directives TYPE_PARSER(sourced(construct( first("DATA" >> pure(llvm::acc::Directive::ACCD_data), "HOST_DATA" >> pure(llvm::acc::Directive::ACCD_host_data), "KERNELS" >> pure(llvm::acc::Directive::ACCD_kernels), "PARALLEL" >> pure(llvm::acc::Directive::ACCD_parallel), "SERIAL" >> pure(llvm::acc::Directive::ACCD_serial))))) // Standalone directives TYPE_PARSER(sourced(construct( first("ENTER DATA" >> pure(llvm::acc::Directive::ACCD_enter_data), "EXIT DATA" >> pure(llvm::acc::Directive::ACCD_exit_data), "INIT" >> pure(llvm::acc::Directive::ACCD_init), "SHUTDOWN" >> pure(llvm::acc::Directive::ACCD_shutdown), "SET" >> pure(llvm::acc::Directive::ACCD_set), "UPDATE" >> pure(llvm::acc::Directive::ACCD_update))))) // Loop directives TYPE_PARSER(sourced(construct( first("LOOP" >> pure(llvm::acc::Directive::ACCD_loop))))) TYPE_PARSER(construct( sourced(Parser{}), Parser{})) TYPE_PARSER(construct("END LOOP"_tok)) TYPE_PARSER(construct( sourced(Parser{} / endAccLine), maybe(Parser{}), maybe(startAccLine >> Parser{} / endAccLine))) // 2.15.1 Routine directive TYPE_PARSER(sourced(construct(verbatim("ROUTINE"_tok), maybe(parenthesized(name)), Parser{}))) // 2.10 Cache directive TYPE_PARSER(sourced( construct(sourced(construct("CACHE"_tok)), parenthesized(Parser{})))) // 2.11 Combined constructs TYPE_PARSER(construct( sourced(Parser{}), Parser{})) // 2.12 Atomic constructs TYPE_PARSER(construct(startAccLine >> "END ATOMIC"_tok)) TYPE_PARSER("ATOMIC" >> construct(verbatim("READ"_tok) / endAccLine, statement(assignmentStmt), maybe(Parser{} / endAccLine))) TYPE_PARSER("ATOMIC" >> construct(verbatim("WRITE"_tok) / endAccLine, statement(assignmentStmt), maybe(Parser{} / endAccLine))) TYPE_PARSER("ATOMIC" >> construct(maybe(verbatim("UPDATE"_tok)) / endAccLine, statement(assignmentStmt), maybe(Parser{} / endAccLine))) TYPE_PARSER("ATOMIC" >> construct(verbatim("CAPTURE"_tok) / endAccLine, statement(assignmentStmt), statement(assignmentStmt), Parser{} / endAccLine)) TYPE_PARSER( sourced(construct(Parser{})) || sourced(construct(Parser{})) || sourced(construct(Parser{})) || sourced(construct(Parser{}))) // 2.13 Declare constructs TYPE_PARSER(sourced(construct( first("DECLARE" >> pure(llvm::acc::Directive::ACCD_declare))))) // [Clause, [Clause], ...] TYPE_PARSER(sourced(construct( many(maybe(","_tok) >> sourced(Parser{}))))) // 2.16.3 Wait directive TYPE_PARSER(sourced(construct( sourced(construct("WAIT"_tok)), maybe(parenthesized(Parser{})), Parser{}))) // Block Constructs TYPE_PARSER(sourced(construct( sourced(Parser{}), Parser{}))) TYPE_PARSER(startAccLine >> sourced(construct("END"_tok >> sourced(Parser{})))) TYPE_PARSER(construct( Parser{} / endAccLine, block, Parser{} / endAccLine)) // Standalone constructs TYPE_PARSER(construct( sourced(Parser{}), Parser{})) // Standalone declarative constructs TYPE_PARSER(construct( sourced(Parser{}), Parser{})) TYPE_PARSER(startAccLine >> withMessage("expected OpenACC directive"_err_en_US, first(sourced(construct( Parser{})), sourced(construct( Parser{}))))) TYPE_PARSER(sourced(construct( "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop)))) // OpenACC constructs TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, startAccLine >> withMessage("expected OpenACC directive"_err_en_US, first(construct(Parser{}), construct(Parser{}), construct(Parser{}), construct( Parser{}), construct(Parser{}), construct(Parser{}), construct(Parser{}), construct(Parser{})))) TYPE_PARSER(startAccLine >> sourced(construct(sourced("END"_tok >> construct("KERNELS"_tok >> maybe("LOOP"_tok) >> pure(llvm::acc::Directive::ACCD_kernels_loop) || "PARALLEL"_tok >> maybe("LOOP"_tok) >> pure(llvm::acc::Directive::ACCD_parallel_loop) || "SERIAL"_tok >> maybe("LOOP"_tok) >> pure(llvm::acc::Directive::ACCD_serial_loop)))))) TYPE_PARSER(construct( sourced(Parser{} / endAccLine), maybe(Parser{}), maybe(Parser{} / endAccLine))) } // namespace Fortran::parser