xref: /llvm-project/flang/runtime/edit-output.h (revision fc97d2e68b03bc2979395e84b645e5b3ba35aecd)
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