xref: /llvm-project/flang/runtime/io-api-minimal.cpp (revision fc97d2e68b03bc2979395e84b645e5b3ba35aecd)
1 //===-- runtime/io-api-minimal.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Implements the subset of the I/O statement API needed for basic
10 // list-directed output (PRINT *) of intrinsic types.
11 
12 #include "edit-output.h"
13 #include "format.h"
14 #include "io-api-common.h"
15 #include "io-stmt.h"
16 #include "terminator.h"
17 #include "tools.h"
18 #include "unit.h"
19 #include "flang/Runtime/io-api.h"
20 
21 namespace Fortran::runtime::io {
22 RT_EXT_API_GROUP_BEGIN
23 
24 Cookie IODEF(BeginExternalListOutput)(
25     ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
26   return BeginExternalListIO<Direction::Output, ExternalListIoStatementState>(
27       unitNumber, sourceFile, sourceLine);
28 }
29 
30 enum Iostat IODEF(EndIoStatement)(Cookie cookie) {
31   IoStatementState &io{*cookie};
32   return static_cast<enum Iostat>(io.EndIoStatement());
33 }
34 
35 template <int KIND, typename INT = CppTypeFor<TypeCategory::Integer, KIND>>
36 inline RT_API_ATTRS bool FormattedScalarIntegerOutput(
37     IoStatementState &io, INT x, const char *whence) {
38   if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
39     auto edit{io.GetNextDataEdit()};
40     return edit && EditIntegerOutput<KIND>(io, *edit, x, /*isSigned=*/true);
41   } else {
42     return false;
43   }
44 }
45 
46 bool IODEF(OutputInteger8)(Cookie cookie, std::int8_t n) {
47   return FormattedScalarIntegerOutput<1>(*cookie, n, "OutputInteger8");
48 }
49 
50 bool IODEF(OutputInteger16)(Cookie cookie, std::int16_t n) {
51   return FormattedScalarIntegerOutput<2>(*cookie, n, "OutputInteger16");
52 }
53 
54 bool IODEF(OutputInteger32)(Cookie cookie, std::int32_t n) {
55   return FormattedScalarIntegerOutput<4>(*cookie, n, "OutputInteger32");
56 }
57 
58 bool IODEF(OutputInteger64)(Cookie cookie, std::int64_t n) {
59   return FormattedScalarIntegerOutput<8>(*cookie, n, "OutputInteger64");
60 }
61 
62 #ifdef __SIZEOF_INT128__
63 bool IODEF(OutputInteger128)(Cookie cookie, common::int128_t n) {
64   return FormattedScalarIntegerOutput<16>(*cookie, n, "OutputInteger128");
65 }
66 #endif
67 
68 template <int KIND,
69     typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint>
70 inline RT_API_ATTRS bool FormattedScalarRealOutput(
71     IoStatementState &io, REAL x, const char *whence) {
72   if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
73     auto edit{io.GetNextDataEdit()};
74     return edit && RealOutputEditing<KIND>{io, x}.Edit(*edit);
75   } else {
76     return false;
77   }
78 }
79 
80 bool IODEF(OutputReal32)(Cookie cookie, float x) {
81   return FormattedScalarRealOutput<4>(*cookie, x, "OutputReal32");
82 }
83 
84 bool IODEF(OutputReal64)(Cookie cookie, double x) {
85   return FormattedScalarRealOutput<8>(*cookie, x, "OutputReal64");
86 }
87 
88 template <int KIND,
89     typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint>
90 inline RT_API_ATTRS bool FormattedScalarComplexOutput(
91     IoStatementState &io, REAL re, REAL im, const char *whence) {
92   if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
93     if (io.get_if<ListDirectedStatementState<Direction::Output>>() != nullptr) {
94       DataEdit rEdit, iEdit;
95       rEdit.descriptor = DataEdit::ListDirectedRealPart;
96       iEdit.descriptor = DataEdit::ListDirectedImaginaryPart;
97       rEdit.modes = iEdit.modes = io.mutableModes();
98       return RealOutputEditing<KIND>{io, re}.Edit(rEdit) &&
99           RealOutputEditing<KIND>{io, im}.Edit(iEdit);
100     } else {
101       auto reEdit{io.GetNextDataEdit()};
102       if (reEdit && RealOutputEditing<KIND>{io, re}.Edit(*reEdit)) {
103         auto imEdit{io.GetNextDataEdit()};
104         return imEdit && RealOutputEditing<KIND>{io, im}.Edit(*imEdit);
105       }
106     }
107   }
108   return false;
109 }
110 
111 bool IODEF(OutputComplex32)(Cookie cookie, float re, float im) {
112   return FormattedScalarComplexOutput<4>(*cookie, re, im, "OutputComplex32");
113 }
114 
115 bool IODEF(OutputComplex64)(Cookie cookie, double re, double im) {
116   return FormattedScalarComplexOutput<8>(*cookie, re, im, "OutputComplex64");
117 }
118 
119 bool IODEF(OutputAscii)(Cookie cookie, const char *x, std::size_t length) {
120   IoStatementState &io{*cookie};
121   if (!x) {
122     io.GetIoErrorHandler().Crash("Null address for character output item");
123   } else if (auto *listOutput{
124                  io.get_if<ListDirectedStatementState<Direction::Output>>()}) {
125     return ListDirectedCharacterOutput(io, *listOutput, x, length);
126   } else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) {
127     auto edit{io.GetNextDataEdit()};
128     return edit && EditCharacterOutput(io, *edit, x, length);
129   } else {
130     return false;
131   }
132 }
133 
134 bool IODEF(OutputLogical)(Cookie cookie, bool truth) {
135   IoStatementState &io{*cookie};
136   if (auto *listOutput{
137           io.get_if<ListDirectedStatementState<Direction::Output>>()}) {
138     return ListDirectedLogicalOutput(io, *listOutput, truth);
139   } else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) {
140     auto edit{io.GetNextDataEdit()};
141     return edit && EditLogicalOutput(io, *edit, truth);
142   } else {
143     return false;
144   }
145 }
146 
147 } // namespace Fortran::runtime::io
148 
149 #if defined(_LIBCPP_VERBOSE_ABORT)
150 // Provide own definition for `std::__libcpp_verbose_abort` to avoid dependency
151 // on the version provided by libc++.
152 
153 void std::__libcpp_verbose_abort(char const *format, ...) {
154   va_list list;
155   va_start(list, format);
156   std::vfprintf(stderr, format, list);
157   va_end(list);
158 
159   std::abort();
160 }
161 #endif
162 
163 RT_EXT_API_GROUP_END
164