llvm/flang/include/flang/Evaluate/target.h

//===-- include/flang/Evaluate/target.h -------------------------*- 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
//
//===----------------------------------------------------------------------===//

// Represents the minimal amount of target architecture information required by
// semantics.

#ifndef FORTRAN_EVALUATE_TARGET_H_
#define FORTRAN_EVALUATE_TARGET_H_

#include "flang/Common/Fortran.h"
#include "flang/Common/enum-class.h"
#include "flang/Common/enum-set.h"
#include "flang/Evaluate/common.h"
#include <cstdint>

namespace Fortran::evaluate {

// Floating-point rounding control
struct Rounding {
  common::RoundingMode mode{common::RoundingMode::TiesToEven};
  // When set, emulate status flag behavior peculiar to x86
  // (viz., fail to set the Underflow flag when an inexact product of a
  // multiplication is rounded up to a normal number from a subnormal
  // in some rounding modes)
#if __x86_64__ || __riscv || __loongarch__
  bool x86CompatibleBehavior{true};
#else
  bool x86CompatibleBehavior{false};
#endif
};

ENUM_CLASS(IeeeFeature, Denormal, Divide, Flags, Halting, Inf, Io, NaN,
    Rounding, Sqrt, Standard, Subnormal, UnderflowControl)

using IeeeFeatures = common::EnumSet<IeeeFeature, 16>;

class TargetCharacteristics {
public:
  TargetCharacteristics();
  TargetCharacteristics &operator=(const TargetCharacteristics &) = default;

  bool isBigEndian() const { return isBigEndian_; }
  void set_isBigEndian(bool isBig = true);

  bool areSubnormalsFlushedToZero() const {
    return areSubnormalsFlushedToZero_;
  }
  void set_areSubnormalsFlushedToZero(bool yes = true);

  Rounding roundingMode() const { return roundingMode_; }
  void set_roundingMode(Rounding);

  std::size_t procedurePointerByteSize() const {
    return procedurePointerByteSize_;
  }
  std::size_t procedurePointerAlignment() const {
    return procedurePointerAlignment_;
  }
  std::size_t descriptorAlignment() const { return descriptorAlignment_; }
  std::size_t maxByteSize() const { return maxByteSize_; }
  std::size_t maxAlignment() const { return maxAlignment_; }

  static bool CanSupportType(common::TypeCategory, std::int64_t kind);
  bool EnableType(common::TypeCategory category, std::int64_t kind,
      std::size_t byteSize, std::size_t align);
  void DisableType(common::TypeCategory category, std::int64_t kind);

  std::size_t GetByteSize(
      common::TypeCategory category, std::int64_t kind) const;
  std::size_t GetAlignment(
      common::TypeCategory category, std::int64_t kind) const;
  bool IsTypeEnabled(common::TypeCategory category, std::int64_t kind) const;

  int SelectedIntKind(std::int64_t precision = 0) const;
  int SelectedLogicalKind(std::int64_t bits = 1) const;
  int SelectedRealKind(std::int64_t precision = 0, std::int64_t range = 0,
      std::int64_t radix = 2) const;

  static Rounding defaultRounding;

  const std::string &compilerOptionsString() const {
    return compilerOptionsString_;
  };
  TargetCharacteristics &set_compilerOptionsString(std::string x) {
    compilerOptionsString_ = x;
    return *this;
  }

  const std::string &compilerVersionString() const {
    return compilerVersionString_;
  };
  TargetCharacteristics &set_compilerVersionString(std::string x) {
    compilerVersionString_ = x;
    return *this;
  }

  bool isPPC() const { return isPPC_; }
  void set_isPPC(bool isPPC = false);

  bool isOSWindows() const { return isOSWindows_; }
  void set_isOSWindows(bool isOSWindows = false) {
    isOSWindows_ = isOSWindows;
  };

  IeeeFeatures &ieeeFeatures() { return ieeeFeatures_; }
  const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }

private:
  static constexpr int maxKind{32};
  std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{};
  std::uint8_t align_[common::TypeCategory_enumSize][maxKind]{};
  bool isBigEndian_{false};
  bool isPPC_{false};
  bool isOSWindows_{false};
  bool areSubnormalsFlushedToZero_{false};
  Rounding roundingMode_{defaultRounding};
  std::size_t procedurePointerByteSize_{8};
  std::size_t procedurePointerAlignment_{8};
  std::size_t descriptorAlignment_{8};
  std::size_t maxByteSize_{8 /*at least*/};
  std::size_t maxAlignment_{8 /*at least*/};
  std::string compilerOptionsString_;
  std::string compilerVersionString_;
  IeeeFeatures ieeeFeatures_{IeeeFeature::Denormal, IeeeFeature::Divide,
      IeeeFeature::Flags, IeeeFeature::Halting, IeeeFeature::Inf,
      IeeeFeature::Io, IeeeFeature::NaN, IeeeFeature::Rounding,
      IeeeFeature::Sqrt, IeeeFeature::Standard, IeeeFeature::Subnormal,
      IeeeFeature::UnderflowControl};
};

} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_TARGET_H_