[flang] Runtime starting and stopping

Define ImageTerminator as a mixin-able class

Turn start.cc into main.cc

Original-commit: flang-compiler/f18@cbc6225213
Reviewed-on: https://github.com/flang-compiler/f18/pull/914
This commit is contained in:
peter klausler 2020-01-08 13:27:32 -08:00
parent 9744328fed
commit aeb07fbea6
9 changed files with 271 additions and 2 deletions

View File

@ -14,7 +14,7 @@
#include <cstring> #include <cstring>
// Define a FormatValidator class template to validate a format expression // Define a FormatValidator class template to validate a format expression
// of a given CHAR kind. To enable use in runtime library code as well as // of a given CHAR type. To enable use in runtime library code as well as
// compiler code, the implementation does its own parsing without recourse // compiler code, the implementation does its own parsing without recourse
// to compiler parser machinery, and avoids features that require C++ runtime // to compiler parser machinery, and avoids features that require C++ runtime
// library support. A format expression is a pointer to a fixed size // library support. A format expression is a pointer to a fixed size
@ -57,6 +57,7 @@ public:
} }
bool Check(); bool Check();
int maxNesting() const { return maxNesting_; }
private: private:
common::EnumSet<TokenKind, TokenKind_enumSize> itemsWithLeadingInts_{ common::EnumSet<TokenKind, TokenKind_enumSize> itemsWithLeadingInts_{
@ -145,6 +146,7 @@ private:
bool unterminatedFormatError_{false}; bool unterminatedFormatError_{false};
bool suppressMessageCascade_{false}; bool suppressMessageCascade_{false};
bool reporterExit_{false}; bool reporterExit_{false};
int maxNesting_{0}; // max level of nested parentheses
}; };
template<typename CHAR> CHAR FormatValidator<CHAR>::NextChar() { template<typename CHAR> CHAR FormatValidator<CHAR>::NextChar() {
@ -682,7 +684,9 @@ template<typename CHAR> bool FormatValidator<CHAR>::Check() {
if (knrValue_ == 0) { if (knrValue_ == 0) {
ReportError("List repeat specifier must be positive", knrToken_); ReportError("List repeat specifier must be positive", knrToken_);
} }
++nestLevel; if (++nestLevel > maxNesting_) {
maxNesting_ = nestLevel;
}
break; break;
case TokenKind::RParen: case TokenKind::RParen:
if (knrValue_ >= 0) { if (knrValue_ >= 0) {

View File

@ -10,6 +10,9 @@ add_library(FortranRuntime
ISO_Fortran_binding.cc ISO_Fortran_binding.cc
derived-type.cc derived-type.cc
descriptor.cc descriptor.cc
main.cc
stop.cc
terminator.cc
transformational.cc transformational.cc
type-code.cc type-code.cc
) )

29
flang/runtime/c-or-cpp.h Normal file
View File

@ -0,0 +1,29 @@
//===-- runtime/c-or-cpp.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#ifndef FORTRAN_RUNTIME_C_OR_CPP_H_
#define FORTRAN_RUNTIME_C_OR_CPP_H_
#ifdef __cplusplus
#define IF_CPLUSPLUS(x) x
#define IF_NOT_CPLUSPLUS(x)
#define DEFAULT_VALUE(x) = (x)
#else
#include <stdbool.h>
#define IF_CPLUSPLUS(x)
#define IF_NOT_CPLUSPLUS(x) x
#define DEFAULT_VALUE(x)
#endif
#define EXTERN_C_BEGIN IF_CPLUSPLUS(extern "C" {)
#define EXTERN_C_END IF_CPLUSPLUS( \
})
#define NORETURN IF_CPLUSPLUS([[noreturn]])
#define NO_ARGUMENTS IF_NOT_CPLUSPLUS(void)
#endif // FORTRAN_RUNTIME_C_OR_CPP_H_

35
flang/runtime/main.cc Normal file
View File

@ -0,0 +1,35 @@
//===-- runtime/main.cc -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#include "main.h"
#include "terminator.h"
#include <cfenv>
#include <cstdlib>
namespace Fortran::runtime {
int argc;
const char **argv;
const char **envp;
}
extern "C" {
void __FortranProgram(); // PROGRAM statement
int main(int argc, const char *argv[], const char *envp[]) {
Fortran::runtime::argc = argc;
Fortran::runtime::argv = argv;
Fortran::runtime::envp = envp;
std::feclearexcept(FE_ALL_EXCEPT);
std::fesetround(FE_TONEAREST);
std::atexit(Fortran::runtime::NotifyOtherImagesOfNormalEnd);
// TODO: Runtime configuration settings from environment
__FortranProgram();
return EXIT_SUCCESS;
}
}

18
flang/runtime/main.h Normal file
View File

@ -0,0 +1,18 @@
//===-- runtime/main.cc -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#ifndef FORTRAN_RUNTIME_MAIN_H_
#define FORTRAN_RUNTIME_MAIN_H_
namespace Fortran::runtime {
extern int argc;
extern const char **argv;
extern const char **envp;
}
#endif // FORTRAN_RUNTIME_MAIN_H_

64
flang/runtime/stop.cc Normal file
View File

@ -0,0 +1,64 @@
//===-- runtime/stop.cc -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#include "stop.h"
#include "terminator.h"
#include <cfenv>
#include <cstdio>
#include <cstdlib>
extern "C" {
static void DescribeIEEESignaledExceptions() {
if (auto excepts{std::fetestexcept(FE_ALL_EXCEPT)}) {
std::fputs("IEEE arithmetic exceptions signaled:", stderr);
if (excepts & FE_DIVBYZERO) {
std::fputs(" DIVBYZERO", stderr);
}
if (excepts & FE_INEXACT) {
std::fputs(" INEXACT", stderr);
}
if (excepts & FE_INVALID) {
std::fputs(" INVALID", stderr);
}
if (excepts & FE_OVERFLOW) {
std::fputs(" OVERFLOW", stderr);
}
if (excepts & FE_UNDERFLOW) {
std::fputs(" UNDERFLOW", stderr);
}
}
}
[[noreturn]] void RTNAME(StopStatement)(
int code, bool isErrorStop, bool quiet) {
if (!quiet) {
if (code != EXIT_SUCCESS) {
std::fprintf(stderr, "Fortran %s: code %d\n",
isErrorStop ? "ERROR STOP" : "STOP", code);
}
DescribeIEEESignaledExceptions();
}
std::exit(code);
}
[[noreturn]] void RTNAME(StopStatementText)(
const char *code, bool isErrorStop, bool quiet) {
if (!quiet) {
std::fprintf(stderr, "Fortran %s: %s\n",
isErrorStop ? "ERROR STOP" : "STOP", code);
DescribeIEEESignaledExceptions();
}
std::exit(EXIT_FAILURE);
}
[[noreturn]] void RTNAME(FailImageStatement)() {
Fortran::runtime::NotifyOtherImagesOfFailImageStatement();
std::exit(EXIT_FAILURE);
}
}

27
flang/runtime/stop.h Normal file
View File

@ -0,0 +1,27 @@
//===-- runtime/stop.h ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#ifndef FORTRAN_RUNTIME_STOP_H_
#define FORTRAN_RUNTIME_STOP_H_
#include "c-or-cpp.h"
#include "entry-names.h"
#include <stdlib.h>
EXTERN_C_BEGIN
// Program-initiated image stop
NORETURN void RTNAME(StopStatement)(int code DEFAULT_VALUE(EXIT_SUCCESS),
bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
NORETURN void RTNAME(StopStatementText)(const char *,
bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
NORETURN void RTNAME(FailImageStatement)(NO_ARGUMENTS);
EXTERN_C_END
#endif // FORTRAN_RUNTIME_STOP_H_

View File

@ -0,0 +1,47 @@
//===-- runtime/terminate.cc ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
#include "terminator.h"
#include <cstdio>
#include <cstdlib>
namespace Fortran::runtime {
[[noreturn]] void Terminator::Crash(const char *message, ...) {
va_list ap;
va_start(ap, message);
CrashArgs(message, ap);
}
[[noreturn]] void Terminator::CrashArgs(const char *message, va_list &ap) {
std::fputs("\nfatal Fortran runtime error", stderr);
if (sourceFileName_) {
std::fprintf(stderr, "(%s", sourceFileName_);
if (sourceLine_) {
std::fprintf(stderr, ":%d", sourceLine_);
}
fputc(')', stderr);
}
std::fputs(": ", stderr);
std::vfprintf(stderr, message, ap);
fputc('\n', stderr);
va_end(ap);
NotifyOtherImagesOfErrorTermination();
std::abort();
}
void NotifyOtherImagesOfNormalEnd() {
// TODO
}
void NotifyOtherImagesOfFailImageStatement() {
// TODO
}
void NotifyOtherImagesOfErrorTermination() {
// TODO
}
}

View File

@ -0,0 +1,42 @@
//===-- runtime/terminator.h ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//----------------------------------------------------------------------------//
// Termination of the image
#ifndef FORTRAN_RUNTIME_TERMINATOR_H_
#define FORTRAN_RUNTIME_TERMINATOR_H_
#include "entry-names.h"
#include <cstdarg>
namespace Fortran::runtime {
// A mixin class for statement-specific image error termination
// for errors detected in the runtime library
class Terminator {
public:
Terminator() {}
explicit Terminator(const char *sourceFileName, int sourceLine = 0)
: sourceFileName_{sourceFileName}, sourceLine_{sourceLine} {}
void SetLocation(const char *sourceFileName = nullptr, int sourceLine = 0) {
sourceFileName_ = sourceFileName;
sourceLine_ = sourceLine;
}
[[noreturn]] void Crash(const char *message, ...);
[[noreturn]] void CrashArgs(const char *message, va_list &);
private:
const char *sourceFileName_{nullptr};
int sourceLine_{0};
};
void NotifyOtherImagesOfNormalEnd();
void NotifyOtherImagesOfFailImageStatement();
void NotifyOtherImagesOfErrorTermination();
}
#endif // FORTRAN_RUNTIME_TERMINATOR_H_