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
26namespace 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.
32template <int KIND>
33bool EditIntegerOutput(
34 IoStatementState &, const DataEdit &, common::HostSignedIntType<8 * KIND>);
35
36// Encapsulates the state of a REAL output conversion.
37class RealOutputEditingBase {
38protected:
39 explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {}
40
41 // Returns null when the exponent overflows a fixed-size output field.
42 const char *FormatExponent(int, const DataEdit &edit, int &length);
43 bool EmitPrefix(const DataEdit &, std::size_t length, std::size_t width);
44 bool EmitSuffix(const DataEdit &);
45
46 IoStatementState &io_;
47 int trailingBlanks_{0}; // created when Gw editing maps to Fw
48 char exponent_[16];
49};
50
51template <int KIND> class RealOutputEditing : public RealOutputEditingBase {
52public:
53 static constexpr int binaryPrecision{common::PrecisionOfRealKind(KIND)};
54 using BinaryFloatingPoint =
55 decimal::BinaryFloatingPointNumber<binaryPrecision>;
56 template <typename A>
57 RealOutputEditing(IoStatementState &io, A x)
58 : RealOutputEditingBase{io}, x_{x} {}
59 bool Edit(const DataEdit &);
60
61private:
62 // The DataEdit arguments here are const references or copies so that
63 // the original DataEdit can safely serve multiple array elements when
64 // it has a repeat count.
65 bool EditEorDOutput(const DataEdit &);
66 bool EditFOutput(const DataEdit &);
67 DataEdit EditForGOutput(DataEdit); // returns an E or F edit
68 bool EditEXOutput(const DataEdit &);
69 bool EditListDirectedOutput(const DataEdit &);
70
71 bool IsZero() const { return x_.IsZero(); }
72
73 decimal::ConversionToDecimalResult ConvertToDecimal(
74 int significantDigits, enum decimal::FortranRounding, int flags = 0);
75
76 struct ConvertToHexadecimalResult {
77 const char *str;
78 int length;
79 int exponent;
80 };
81 ConvertToHexadecimalResult ConvertToHexadecimal(
82 int significantDigits, enum decimal::FortranRounding, int flags = 0);
83
84 BinaryFloatingPoint x_;
85 char buffer_[BinaryFloatingPoint::maxDecimalConversionDigits +
86 EXTRA_DECIMAL_CONVERSION_SPACE];
87};
88
89bool ListDirectedLogicalOutput(
90 IoStatementState &, ListDirectedStatementState<Direction::Output> &, bool);
91bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool);
92
93template <typename CHAR>
94bool ListDirectedCharacterOutput(IoStatementState &,
95 ListDirectedStatementState<Direction::Output> &, const CHAR *,
96 std::size_t chars);
97extern template bool ListDirectedCharacterOutput(IoStatementState &,
98 ListDirectedStatementState<Direction::Output> &, const char *,
99 std::size_t chars);
100extern template bool ListDirectedCharacterOutput(IoStatementState &,
101 ListDirectedStatementState<Direction::Output> &, const char16_t *,
102 std::size_t chars);
103extern template bool ListDirectedCharacterOutput(IoStatementState &,
104 ListDirectedStatementState<Direction::Output> &, const char32_t *,
105 std::size_t chars);
106
107template <typename CHAR>
108bool EditCharacterOutput(
109 IoStatementState &, const DataEdit &, const CHAR *, std::size_t chars);
110extern template bool EditCharacterOutput(
111 IoStatementState &, const DataEdit &, const char *, std::size_t chars);
112extern template bool EditCharacterOutput(
113 IoStatementState &, const DataEdit &, const char16_t *, std::size_t chars);
114extern template bool EditCharacterOutput(
115 IoStatementState &, const DataEdit &, const char32_t *, std::size_t chars);
116
117extern template bool EditIntegerOutput<1>(
118 IoStatementState &, const DataEdit &, std::int8_t);
119extern template bool EditIntegerOutput<2>(
120 IoStatementState &, const DataEdit &, std::int16_t);
121extern template bool EditIntegerOutput<4>(
122 IoStatementState &, const DataEdit &, std::int32_t);
123extern template bool EditIntegerOutput<8>(
124 IoStatementState &, const DataEdit &, std::int64_t);
125extern template bool EditIntegerOutput<16>(
126 IoStatementState &, const DataEdit &, common::int128_t);
127
128extern template class RealOutputEditing<2>;
129extern template class RealOutputEditing<3>;
130extern template class RealOutputEditing<4>;
131extern template class RealOutputEditing<8>;
132extern template class RealOutputEditing<10>;
133// TODO: double/double
134extern template class RealOutputEditing<16>;
135
136} // namespace Fortran::runtime::io
137#endif // FORTRAN_RUNTIME_EDIT_OUTPUT_H_
138

source code of flang/runtime/edit-output.h