/*
 * Copyright 2015, The Android Open Source Project
 *
 * 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 _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_REDUCE_H_  // NOLINT
#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_REDUCE_H_

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"

#include "slang_rs_context.h"
#include "slang_rs_exportable.h"
#include "slang_rs_export_type.h"

namespace clang {
  class FunctionDecl;
}  // namespace clang

namespace slang {

// Base class for reflecting control-side reduce
class RSExportReduce : public RSExportable {
 public:
  typedef llvm::SmallVectorImpl<const clang::ParmVarDecl*> InVec;
  typedef llvm::SmallVectorImpl<const RSExportType*> InTypeVec;

  typedef InVec::const_iterator InIter;
  typedef InTypeVec::const_iterator InTypeIter;

 private:
  // pragma location (for error reporting)
  clang::SourceLocation mLocation;

  // reduction kernel name
  std::string mNameReduce;

  // constituent function names
  std::string mNameInitializer;
  std::string mNameAccumulator;
  std::string mNameCombiner;
  std::string mNameOutConverter;
  std::string mNameHalter;

  // constituent function identity
  enum FnIdent {
    FN_IDENT_INITIALIZER,
    FN_IDENT_ACCUMULATOR,
    FN_IDENT_COMBINER,
    FN_IDENT_OUT_CONVERTER,
    FN_IDENT_HALTER
  };
  static const char *getKey(FnIdent Kind);

  // signature information for accumulator function
  unsigned int mAccumulatorSignatureMetadata;

  // size of accumulator data type (compType), in bytes
  unsigned int mAccumulatorTypeSize;

  // input information for accumulator function
  static const int kAccumulatorInsSmallSize = 4;
  llvm::SmallVector<const clang::ParmVarDecl*, kAccumulatorInsSmallSize> mAccumulatorIns;
  llvm::SmallVector<const RSExportType*, kAccumulatorInsSmallSize> mAccumulatorInTypes;

  // result information
  RSExportType *mResultType;

  RSExportReduce(RSContext *Context,
                 const clang::SourceLocation Location,
                 const llvm::StringRef &NameReduce,
                 const llvm::StringRef &NameInitializer,
                 const llvm::StringRef &NameAccumulator,
                 const llvm::StringRef &NameCombiner,
                 const llvm::StringRef &NameOutConverter,
                 const llvm::StringRef &NameHalter)
    : RSExportable(Context, RSExportable::EX_REDUCE),
      mLocation(Location),
      mNameReduce(NameReduce),
      mNameInitializer(NameInitializer),
      mNameAccumulator(NameAccumulator),
      mNameCombiner(NameCombiner),
      mNameOutConverter(NameOutConverter),
      mNameHalter(NameHalter),
      mAccumulatorSignatureMetadata(0),
      mAccumulatorTypeSize(0),
      mResultType(nullptr) {
  }

  RSExportReduce(const RSExportReduce &) = delete;
  void operator=(const RSExportReduce &) = delete;

  struct StateOfAnalyzeTranslationUnit;

  static void notOk(StateOfAnalyzeTranslationUnit &S, FnIdent Kind);

  static void checkPointeeConstQualified(StateOfAnalyzeTranslationUnit &S,
                                         FnIdent Kind, const llvm::StringRef &Name,
                                         const clang::ParmVarDecl *Param, bool ExpectedQualification);

  static void checkVoidReturn(StateOfAnalyzeTranslationUnit &S, FnIdent Kind, clang::FunctionDecl *Fn);

  clang::FunctionDecl *lookupFunction(StateOfAnalyzeTranslationUnit &S,
                                      const char *Kind, const llvm::StringRef &Name);

  void analyzeInitializer(StateOfAnalyzeTranslationUnit &S);
  void analyzeAccumulator(StateOfAnalyzeTranslationUnit &S);
  void analyzeCombiner(StateOfAnalyzeTranslationUnit &S);
  void analyzeOutConverter(StateOfAnalyzeTranslationUnit &S);
  void analyzeHalter(StateOfAnalyzeTranslationUnit &S);
  void analyzeResultType(StateOfAnalyzeTranslationUnit &S);

 public:

  static const char KeyReduce[];
  static const char KeyInitializer[];
  static const char KeyAccumulator[];
  static const char KeyCombiner[];
  static const char KeyOutConverter[];
  static const char KeyHalter[];

  static RSExportReduce *Create(RSContext *Context,
                                const clang::SourceLocation Location,
                                const llvm::StringRef &NameReduce,
                                const llvm::StringRef &NameInitializer,
                                const llvm::StringRef &NameAccumulator,
                                const llvm::StringRef &NameCombiner,
                                const llvm::StringRef &NameOutConverter,
                                const llvm::StringRef &NameHalter);

  const clang::SourceLocation &getLocation() const { return mLocation; }

  const std::string &getNameReduce() const { return mNameReduce; }
  const std::string &getNameInitializer() const { return mNameInitializer; }
  const std::string &getNameAccumulator() const { return mNameAccumulator; }
  const std::string &getNameCombiner() const { return mNameCombiner; }
  const std::string &getNameOutConverter() const { return mNameOutConverter; }
  const std::string &getNameHalter() const { return mNameHalter; }

  unsigned int getAccumulatorSignatureMetadata() const { return mAccumulatorSignatureMetadata; }

  unsigned int getAccumulatorTypeSize() const { return mAccumulatorTypeSize; }

  const InVec &getAccumulatorIns() const { return mAccumulatorIns; }
  const InTypeVec &getAccumulatorInTypes() const { return mAccumulatorInTypes; }

  const RSExportType *getResultType() const { return mResultType; }

  // Does one of this reduction's constituent function names match Candidate?
  bool matchName(const llvm::StringRef &Candidate) const;

  bool analyzeTranslationUnit();
};  // RSExportReduce

}  // namespace slang

#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_EXPORT_REDUCE_H_  NOLINT
