llvm-project
154 строки · 4.2 Кб
1//===-- runtime/stop.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#include "flang/Runtime/stop.h"
10#include "environment.h"
11#include "file.h"
12#include "io-error.h"
13#include "terminator.h"
14#include "unit.h"
15#include <cfenv>
16#include <cstdio>
17#include <cstdlib>
18
19extern "C" {
20
21static void DescribeIEEESignaledExceptions() {
22#ifdef fetestexcept // a macro in some environments; omit std::
23auto excepts{fetestexcept(FE_ALL_EXCEPT)};
24#else
25auto excepts{std::fetestexcept(FE_ALL_EXCEPT)};
26#endif
27if (excepts) {
28std::fputs("IEEE arithmetic exceptions signaled:", stderr);
29if (excepts & FE_DIVBYZERO) {
30std::fputs(" DIVBYZERO", stderr);
31}
32if (excepts & FE_INEXACT) {
33std::fputs(" INEXACT", stderr);
34}
35if (excepts & FE_INVALID) {
36std::fputs(" INVALID", stderr);
37}
38if (excepts & FE_OVERFLOW) {
39std::fputs(" OVERFLOW", stderr);
40}
41if (excepts & FE_UNDERFLOW) {
42std::fputs(" UNDERFLOW", stderr);
43}
44std::fputc('\n', stderr);
45}
46}
47
48static void CloseAllExternalUnits(const char *why) {
49Fortran::runtime::io::IoErrorHandler handler{why};
50Fortran::runtime::io::ExternalFileUnit::CloseAll(handler);
51}
52
53[[noreturn]] void RTNAME(StopStatement)(
54int code, bool isErrorStop, bool quiet) {
55CloseAllExternalUnits("STOP statement");
56if (Fortran::runtime::executionEnvironment.noStopMessage && code == 0) {
57quiet = true;
58}
59if (!quiet) {
60std::fprintf(stderr, "Fortran %s", isErrorStop ? "ERROR STOP" : "STOP");
61if (code != EXIT_SUCCESS) {
62std::fprintf(stderr, ": code %d\n", code);
63}
64std::fputc('\n', stderr);
65DescribeIEEESignaledExceptions();
66}
67std::exit(code);
68}
69
70[[noreturn]] void RTNAME(StopStatementText)(
71const char *code, std::size_t length, bool isErrorStop, bool quiet) {
72CloseAllExternalUnits("STOP statement");
73if (!quiet) {
74if (Fortran::runtime::executionEnvironment.noStopMessage && !isErrorStop) {
75std::fprintf(stderr, "%.*s\n", static_cast<int>(length), code);
76} else {
77std::fprintf(stderr, "Fortran %s: %.*s\n",
78isErrorStop ? "ERROR STOP" : "STOP", static_cast<int>(length), code);
79}
80DescribeIEEESignaledExceptions();
81}
82if (isErrorStop) {
83std::exit(EXIT_FAILURE);
84} else {
85std::exit(EXIT_SUCCESS);
86}
87}
88
89static bool StartPause() {
90if (Fortran::runtime::io::IsATerminal(0)) {
91Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"};
92Fortran::runtime::io::ExternalFileUnit::FlushAll(handler);
93return true;
94}
95return false;
96}
97
98static void EndPause() {
99std::fflush(nullptr);
100if (std::fgetc(stdin) == EOF) {
101CloseAllExternalUnits("PAUSE statement");
102std::exit(EXIT_SUCCESS);
103}
104}
105
106void RTNAME(PauseStatement)() {
107if (StartPause()) {
108std::fputs("Fortran PAUSE: hit RETURN to continue:", stderr);
109EndPause();
110}
111}
112
113void RTNAME(PauseStatementInt)(int code) {
114if (StartPause()) {
115std::fprintf(stderr, "Fortran PAUSE %d: hit RETURN to continue:", code);
116EndPause();
117}
118}
119
120void RTNAME(PauseStatementText)(const char *code, std::size_t length) {
121if (StartPause()) {
122std::fprintf(stderr,
123"Fortran PAUSE %.*s: hit RETURN to continue:", static_cast<int>(length),
124code);
125EndPause();
126}
127}
128
129[[noreturn]] void RTNAME(FailImageStatement)() {
130Fortran::runtime::NotifyOtherImagesOfFailImageStatement();
131CloseAllExternalUnits("FAIL IMAGE statement");
132std::exit(EXIT_FAILURE);
133}
134
135[[noreturn]] void RTNAME(ProgramEndStatement)() {
136CloseAllExternalUnits("END statement");
137std::exit(EXIT_SUCCESS);
138}
139
140[[noreturn]] void RTNAME(Exit)(int status) {
141CloseAllExternalUnits("CALL EXIT()");
142std::exit(status);
143}
144
145[[noreturn]] void RTNAME(Abort)() {
146// TODO: Add backtrace call, unless with `-fno-backtrace`.
147std::abort();
148}
149
150[[noreturn]] void RTNAME(ReportFatalUserError)(
151const char *message, const char *source, int line) {
152Fortran::runtime::Terminator{source, line}.Crash(message);
153}
154}
155