text: //===-- Optimizer/Support/KindMapping.h -- support kind mapping -*- C++ -*-===//
  //
  // 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
  //
  //===----------------------------------------------------------------------===//
  //
  // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
  #define FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
  
  #include "mlir/IR/OpDefinition.h"
  #include "llvm/ADT/DenseMap.h"
  #include "llvm/IR/Type.h"
  
  namespace llvm {
  struct fltSemantics;
  } // namespace llvm
  
  namespace fir {
  
  /// The kind mapping is an encoded string that informs FIR how the Fortran KIND
  /// values from the front-end should be converted to LLVM IR types.  This
  /// encoding allows the mapping from front-end KIND values to backend LLVM IR
  /// types to be customized by the front-end.
  ///
  /// The provided string uses the following syntax.
  ///
  ///   intrinsic-key `:` kind-value (`,` intrinsic-key `:` kind-value)*
  ///
  /// intrinsic-key is a single character for the intrinsic type.
  ///   'i' : INTEGER   (size in bits)
  ///   'l' : LOGICAL   (size in bits)
  ///   'a' : CHARACTER (size in bits)
  ///   'r' : REAL    (encoding value)
  ///   'c' : COMPLEX (encoding value)
  ///
  /// kind-value is either an unsigned integer (for 'i', 'l', and 'a') or one of
  /// 'Half', 'BFloat', 'Float', 'Double', 'X86_FP80', or 'FP128' (for 'r' and
  /// 'c').
  ///
  /// If LLVM adds support for new floating-point types, the final list should be
  /// extended.
  class KindMapping {
  public:
    using KindTy = unsigned;
    using Bitsize = unsigned;
    using LLVMTypeID = llvm::Type::TypeID;
    using MatchResult = mlir::ParseResult;
  
    /// KindMapping constructor with both the kind map and default kinds read from
    /// command-line options.
    explicit KindMapping(mlir::MLIRContext *context);
    /// KindMapping constructor taking a `defs` argument to specify the default
    /// kinds for intrinsic types. To set the default kinds, an ArrayRef of 6
    /// KindTy must be passed. The kinds must be the given in the following order:
    /// CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL.  The
    /// kind map is read from command-line options, if given.
    explicit KindMapping(mlir::MLIRContext *context, llvm::ArrayRef<KindTy> defs);
    /// KindMapping constructor taking an optional `defs` argument to specify the
    /// default kinds for intrinsic types. To set the default kinds, an ArrayRef
    /// of 6 KindTy must be passed. The kinds must be the given in the following
    /// order: CHARACTER, COMPLEX, DOUBLE PRECISION, INTEGER, LOGICAL, and REAL.
    explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
                         llvm::ArrayRef<KindTy> defs = llvm::None);
    explicit KindMapping(mlir::MLIRContext *context, llvm::StringRef map,
                         llvm::StringRef defs)
        : KindMapping{context, map, toDefaultKinds(defs)} {}
  
    /// Get the size in bits of !fir.char<kind>
    Bitsize getCharacterBitsize(KindTy kind) const;
  
    /// Get the size in bits of !fir.int<kind>
    Bitsize getIntegerBitsize(KindTy kind) const;
  
    /// Get the size in bits of !fir.logical<kind>
    Bitsize getLogicalBitsize(KindTy kind) const;
  
    /// Get the size in bits of !fir.real<kind>
    Bitsize getRealBitsize(KindTy kind) const;
  
    /// Get the LLVM Type::TypeID of !fir.real<kind>
    LLVMTypeID getRealTypeID(KindTy kind) const;
  
    /// Get the LLVM Type::TypeID of !fir.complex<kind>
    LLVMTypeID getComplexTypeID(KindTy kind) const;
  
    mlir::MLIRContext *getContext() const { return context; }
  
    /// Get the float semantics of !fir.real<kind>
    const llvm::fltSemantics &getFloatSemantics(KindTy kind) const;
  
    /// Get the default kind map as a string.
    static constexpr const char *getDefaultMap() { return ""; }
  
    /// Convert the current kind map to a string.
    std::string mapToString() const;
  
    //===--------------------------------------------------------------------===//
    // Default kinds of intrinsic types
    //===--------------------------------------------------------------------===//
  
    KindTy defaultCharacterKind() const;
    KindTy defaultComplexKind() const;
    KindTy defaultDoubleKind() const;
    KindTy defaultIntegerKind() const;
    KindTy defaultLogicalKind() const;
    KindTy defaultRealKind() const;
  
    /// Get the default kinds as a string.
    static constexpr const char *getDefaultKinds() { return "a1c4d8i4l4r4"; }
  
    /// Convert the current default kinds to a string.
    std::string defaultsToString() const;
  
    /// Translate a default kinds string into a default kind vector. This vector
    /// can be passed to the KindMapping ctor.
    static std::vector<KindTy> toDefaultKinds(llvm::StringRef defs);
  
  private:
    MatchResult badMapString(const llvm::Twine &ptr);
    MatchResult parse(llvm::StringRef kindMap);
    mlir::LogicalResult setDefaultKinds(llvm::ArrayRef<KindTy> defs);
  
    mlir::MLIRContext *context;
    llvm::DenseMap<std::pair<char, KindTy>, Bitsize> intMap;
    llvm::DenseMap<std::pair<char, KindTy>, LLVMTypeID> floatMap;
    llvm::DenseMap<char, KindTy> defaultMap;
  };
  
  } // namespace fir
  
  #endif // FORTRAN_OPTIMIZER_SUPPORT_KINDMAPPING_H
  