brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · c443278 Raw
271 lines · cpp
1//===-- lib/Semantics/target.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Evaluate/target.h"10#include "flang/Common/template.h"11#include "flang/Common/type-kinds.h"12#include "flang/Evaluate/common.h"13#include "flang/Evaluate/type.h"14 15namespace Fortran::evaluate {16 17Rounding TargetCharacteristics::defaultRounding;18 19TargetCharacteristics::TargetCharacteristics() {20  auto enableCategoryKinds{[this](TypeCategory category) {21    for (int kind{1}; kind <= maxKind; ++kind) {22      if (CanSupportType(category, kind)) {23        auto byteSize{24            static_cast<std::size_t>(common::TypeSizeInBytes(category, kind))};25        std::size_t align{byteSize};26        if (category == TypeCategory::Complex) {27          align /= 2;28        }29        EnableType(category, kind, byteSize, align);30      }31    }32  }};33  enableCategoryKinds(TypeCategory::Integer);34  enableCategoryKinds(TypeCategory::Real);35  enableCategoryKinds(TypeCategory::Complex);36  enableCategoryKinds(TypeCategory::Character);37  enableCategoryKinds(TypeCategory::Logical);38  enableCategoryKinds(TypeCategory::Unsigned);39 40  isBigEndian_ = !isHostLittleEndian;41 42  areSubnormalsFlushedToZero_ = false;43}44 45bool TargetCharacteristics::CanSupportType(46    TypeCategory category, std::int64_t kind) {47  return common::IsValidKindOfIntrinsicType(category, kind);48}49 50bool TargetCharacteristics::EnableType(common::TypeCategory category,51    std::int64_t kind, std::size_t byteSize, std::size_t align) {52  if (CanSupportType(category, kind)) {53    byteSize_[static_cast<int>(category)][kind] = byteSize;54    align_[static_cast<int>(category)][kind] = align;55    maxByteSize_ = std::max(maxByteSize_, byteSize);56    maxAlignment_ = std::max(maxAlignment_, align);57    return true;58  } else {59    return false;60  }61}62 63void TargetCharacteristics::DisableType(64    common::TypeCategory category, std::int64_t kind) {65  if (kind > 0 && kind <= maxKind) {66    align_[static_cast<int>(category)][kind] = 0;67  }68}69 70std::size_t TargetCharacteristics::GetByteSize(71    common::TypeCategory category, std::int64_t kind) const {72  if (kind > 0 && kind <= maxKind) {73    return byteSize_[static_cast<int>(category)][kind];74  } else {75    return 0;76  }77}78 79std::size_t TargetCharacteristics::GetAlignment(80    common::TypeCategory category, std::int64_t kind) const {81  if (kind > 0 && kind <= maxKind) {82    return align_[static_cast<int>(category)][kind];83  } else {84    return 0;85  }86}87 88bool TargetCharacteristics::IsTypeEnabled(89    common::TypeCategory category, std::int64_t kind) const {90  return GetAlignment(category, kind) > 0;91}92 93void TargetCharacteristics::set_isBigEndian(bool isBig) {94  isBigEndian_ = isBig;95}96 97void TargetCharacteristics::set_isPPC(bool isPowerPC) { isPPC_ = isPowerPC; }98void TargetCharacteristics::set_isSPARC(bool isSPARC) { isSPARC_ = isSPARC; }99 100void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {101  areSubnormalsFlushedToZero_ = yes;102}103 104// Check if a given real kind has flushing control.105bool TargetCharacteristics::hasSubnormalFlushingControl(int kind) const {106  CHECK(kind > 0 && kind <= maxKind);107  CHECK(CanSupportType(TypeCategory::Real, kind));108  return hasSubnormalFlushingControl_[kind];109}110 111// Check if any or all real kinds have flushing control.112bool TargetCharacteristics::hasSubnormalFlushingControl(bool any) const {113  for (int kind{1}; kind <= maxKind; ++kind) {114    if (CanSupportType(TypeCategory::Real, kind) &&115        hasSubnormalFlushingControl_[kind] == any) {116      return any;117    }118  }119  return !any;120}121 122void TargetCharacteristics::set_hasSubnormalFlushingControl(123    int kind, bool yes) {124  CHECK(kind > 0 && kind <= maxKind);125  hasSubnormalFlushingControl_[kind] = yes;126}127 128// Check if a given real kind has (nonstandard) ieee_denorm exception control.129bool TargetCharacteristics::hasSubnormalExceptionSupport(int kind) const {130  CHECK(kind > 0 && kind <= maxKind);131  CHECK(CanSupportType(TypeCategory::Real, kind));132  return hasSubnormalExceptionSupport_[kind];133}134 135// Check if all real kinds have support for the ieee_denorm exception.136bool TargetCharacteristics::hasSubnormalExceptionSupport() const {137  for (int kind{1}; kind <= maxKind; ++kind) {138    if (CanSupportType(TypeCategory::Real, kind) &&139        !hasSubnormalExceptionSupport_[kind]) {140      return false;141    }142  }143  return true;144}145 146void TargetCharacteristics::set_hasSubnormalExceptionSupport(147    int kind, bool yes) {148  CHECK(kind > 0 && kind <= maxKind);149  hasSubnormalExceptionSupport_[kind] = yes;150}151 152void TargetCharacteristics::set_roundingMode(Rounding rounding) {153  roundingMode_ = rounding;154}155 156// SELECTED_INT_KIND() -- F'2018 16.9.169157// and SELECTED_UNSIGNED_KIND() extension (same results)158class SelectedIntKindVisitor {159public:160  SelectedIntKindVisitor(161      const TargetCharacteristics &targetCharacteristics, std::int64_t p)162      : targetCharacteristics_{targetCharacteristics}, precision_{p} {}163  using Result = std::optional<int>;164  using Types = IntegerTypes;165  template <typename T> Result Test() const {166    if (Scalar<T>::RANGE >= precision_ &&167        targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {168      return T::kind;169    } else {170      return std::nullopt;171    }172  }173 174private:175  const TargetCharacteristics &targetCharacteristics_;176  std::int64_t precision_;177};178 179int TargetCharacteristics::SelectedIntKind(std::int64_t precision) const {180  if (auto kind{181          common::SearchTypes(SelectedIntKindVisitor{*this, precision})}) {182    return *kind;183  } else {184    return -1;185  }186}187 188// SELECTED_LOGICAL_KIND() -- F'2023 16.9.182189class SelectedLogicalKindVisitor {190public:191  SelectedLogicalKindVisitor(192      const TargetCharacteristics &targetCharacteristics, std::int64_t bits)193      : targetCharacteristics_{targetCharacteristics}, bits_{bits} {}194  using Result = std::optional<int>;195  using Types = LogicalTypes;196  template <typename T> Result Test() const {197    if (Scalar<T>::bits >= bits_ &&198        targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {199      return T::kind;200    } else {201      return std::nullopt;202    }203  }204 205private:206  const TargetCharacteristics &targetCharacteristics_;207  std::int64_t bits_;208};209 210int TargetCharacteristics::SelectedLogicalKind(std::int64_t bits) const {211  if (auto kind{common::SearchTypes(SelectedLogicalKindVisitor{*this, bits})}) {212    return *kind;213  } else {214    return -1;215  }216}217 218// SELECTED_REAL_KIND() -- F'2018 16.9.170219class SelectedRealKindVisitor {220public:221  SelectedRealKindVisitor(const TargetCharacteristics &targetCharacteristics,222      std::int64_t p, std::int64_t r)223      : targetCharacteristics_{targetCharacteristics}, precision_{p}, range_{224                                                                          r} {}225  using Result = std::optional<int>;226  using Types = RealTypes;227  template <typename T> Result Test() const {228    if (Scalar<T>::PRECISION >= precision_ && Scalar<T>::RANGE >= range_ &&229        targetCharacteristics_.IsTypeEnabled(T::category, T::kind)) {230      return {T::kind};231    } else {232      return std::nullopt;233    }234  }235 236private:237  const TargetCharacteristics &targetCharacteristics_;238  std::int64_t precision_, range_;239};240 241int TargetCharacteristics::SelectedRealKind(242    std::int64_t precision, std::int64_t range, std::int64_t radix) const {243  if (radix != 2) {244    return -5;245  }246  if (auto kind{common::SearchTypes(247          SelectedRealKindVisitor{*this, precision, range})}) {248    return *kind;249  }250  // No kind has both sufficient precision and sufficient range.251  // The negative return value encodes whether any kinds exist that252  // could satisfy either constraint independently.253  bool pOK{common::SearchTypes(SelectedRealKindVisitor{*this, precision, 0})};254  bool rOK{common::SearchTypes(SelectedRealKindVisitor{*this, 0, range})};255  if (pOK) {256    if (rOK) {257      return -4;258    } else {259      return -2;260    }261  } else {262    if (rOK) {263      return -1;264    } else {265      return -3;266    }267  }268}269 270} // namespace Fortran::evaluate271