1 //===-- runtime/edit-output.h -----------------------------------*- C++ -*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_RUNTIME_EDIT_OUTPUT_H_ 10 #define FORTRAN_RUNTIME_EDIT_OUTPUT_H_ 11 12 // Output data editing templates implementing the FORMAT data editing 13 // descriptors E, EN, ES, EX, D, F, and G for REAL data (and COMPLEX 14 // components, I and G for INTEGER, and B/O/Z for both. 15 // See subclauses in 13.7.2.3 of Fortran 2018 for the 16 // detailed specifications of these descriptors. 17 // List-directed output (13.10.4) for numeric types is also done here. 18 // Drives the same fast binary-to-decimal formatting templates used 19 // in the f18 front-end. 20 21 #include "format.h" 22 #include "io-stmt.h" 23 #include "flang/Common/uint128.h" 24 #include "flang/Decimal/decimal.h" 25 26 namespace Fortran::runtime::io { 27 28 // I, B, O, Z, and G output editing for INTEGER. 29 // The DataEdit reference is const here (and elsewhere in this header) so that 30 // one edit descriptor with a repeat factor may safely serve to edit 31 // multiple elements of an array. 32 template <int KIND> 33 RT_API_ATTRS bool EditIntegerOutput(IoStatementState &, const DataEdit &, 34 common::HostSignedIntType<8 * KIND>, bool isSigned); 35 36 // Encapsulates the state of a REAL output conversion. 37 class RealOutputEditingBase { 38 protected: 39 explicit RT_API_ATTRS RealOutputEditingBase(IoStatementState &io) : io_{io} {} 40 41 // Returns null when the exponent overflows a fixed-size output field. 42 RT_API_ATTRS const char *FormatExponent( 43 int, const DataEdit &edit, int &length); 44 RT_API_ATTRS bool EmitPrefix( 45 const DataEdit &, std::size_t length, std::size_t width); 46 RT_API_ATTRS bool EmitSuffix(const DataEdit &); 47 48 IoStatementState &io_; 49 int trailingBlanks_{0}; // created when Gw editing maps to Fw 50 char exponent_[16]; 51 }; 52 53 template <int KIND> class RealOutputEditing : public RealOutputEditingBase { 54 public: 55 RT_VAR_GROUP_BEGIN 56 static constexpr int binaryPrecision{common::PrecisionOfRealKind(KIND)}; 57 RT_VAR_GROUP_END 58 using BinaryFloatingPoint = 59 decimal::BinaryFloatingPointNumber<binaryPrecision>; 60 template <typename A> 61 RT_API_ATTRS RealOutputEditing(IoStatementState &io, A x) 62 : RealOutputEditingBase{io}, x_{x} {} 63 RT_API_ATTRS bool Edit(const DataEdit &); 64 65 private: 66 // The DataEdit arguments here are const references or copies so that 67 // the original DataEdit can safely serve multiple array elements when 68 // it has a repeat count. 69 RT_API_ATTRS bool EditEorDOutput(const DataEdit &); 70 RT_API_ATTRS bool EditFOutput(const DataEdit &); 71 RT_API_ATTRS DataEdit EditForGOutput(DataEdit); // returns an E or F edit 72 RT_API_ATTRS bool EditEXOutput(const DataEdit &); 73 RT_API_ATTRS bool EditListDirectedOutput(const DataEdit &); 74 75 RT_API_ATTRS bool IsZero() const { return x_.IsZero(); } 76 77 RT_API_ATTRS decimal::ConversionToDecimalResult ConvertToDecimal( 78 int significantDigits, enum decimal::FortranRounding, int flags = 0); 79 80 struct ConvertToHexadecimalResult { 81 const char *str; 82 int length; 83 int exponent; 84 }; 85 RT_API_ATTRS ConvertToHexadecimalResult ConvertToHexadecimal( 86 int significantDigits, enum decimal::FortranRounding, int flags = 0); 87 88 BinaryFloatingPoint x_; 89 char buffer_[BinaryFloatingPoint::maxDecimalConversionDigits + 90 EXTRA_DECIMAL_CONVERSION_SPACE]; 91 }; 92 93 RT_API_ATTRS bool ListDirectedLogicalOutput( 94 IoStatementState &, ListDirectedStatementState<Direction::Output> &, bool); 95 RT_API_ATTRS bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool); 96 97 template <typename CHAR> 98 RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &, 99 ListDirectedStatementState<Direction::Output> &, const CHAR *, 100 std::size_t chars); 101 extern template RT_API_ATTRS bool ListDirectedCharacterOutput( 102 IoStatementState &, ListDirectedStatementState<Direction::Output> &, 103 const char *, std::size_t chars); 104 extern template RT_API_ATTRS bool ListDirectedCharacterOutput( 105 IoStatementState &, ListDirectedStatementState<Direction::Output> &, 106 const char16_t *, std::size_t chars); 107 extern template RT_API_ATTRS bool ListDirectedCharacterOutput( 108 IoStatementState &, ListDirectedStatementState<Direction::Output> &, 109 const char32_t *, std::size_t chars); 110 111 template <typename CHAR> 112 RT_API_ATTRS bool EditCharacterOutput( 113 IoStatementState &, const DataEdit &, const CHAR *, std::size_t chars); 114 extern template RT_API_ATTRS bool EditCharacterOutput( 115 IoStatementState &, const DataEdit &, const char *, std::size_t chars); 116 extern template RT_API_ATTRS bool EditCharacterOutput( 117 IoStatementState &, const DataEdit &, const char16_t *, std::size_t chars); 118 extern template RT_API_ATTRS bool EditCharacterOutput( 119 IoStatementState &, const DataEdit &, const char32_t *, std::size_t chars); 120 121 extern template RT_API_ATTRS bool EditIntegerOutput<1>( 122 IoStatementState &, const DataEdit &, std::int8_t, bool); 123 extern template RT_API_ATTRS bool EditIntegerOutput<2>( 124 IoStatementState &, const DataEdit &, std::int16_t, bool); 125 extern template RT_API_ATTRS bool EditIntegerOutput<4>( 126 IoStatementState &, const DataEdit &, std::int32_t, bool); 127 extern template RT_API_ATTRS bool EditIntegerOutput<8>( 128 IoStatementState &, const DataEdit &, std::int64_t, bool); 129 extern template RT_API_ATTRS bool EditIntegerOutput<16>( 130 IoStatementState &, const DataEdit &, common::int128_t, bool); 131 132 extern template class RealOutputEditing<2>; 133 extern template class RealOutputEditing<3>; 134 extern template class RealOutputEditing<4>; 135 extern template class RealOutputEditing<8>; 136 extern template class RealOutputEditing<10>; 137 // TODO: double/double 138 extern template class RealOutputEditing<16>; 139 140 } // namespace Fortran::runtime::io 141 #endif // FORTRAN_RUNTIME_EDIT_OUTPUT_H_ 142