llvm-project/flang/lib/Semantics/mod-file.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

84 lines
2.5 KiB
C
Raw Normal View History

//===-- lib/Semantics/mod-file.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_SEMANTICS_MOD_FILE_H_
#define FORTRAN_SEMANTICS_MOD_FILE_H_
#include "flang/Semantics/attr.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
namespace Fortran::parser {
class CharBlock;
[flang] Improve module file reading and writing Fix problems with writing a mod file while another compilation is reading or writing. Write to a temp and then rename it: - compute the new contents of the .mod file - if it already exists, check if it is already correct - if not, write new contents to a temp file - rename the temp to the final destination `mkstemps()` seems to be the best way to create the temp file. It returns a file descriptor, so change the rest of the mod file writing to use POSIX open/read/write/close. This seems to set errno more reliably too. There is some extra work around creating the temp to make it have the same directory and suffix as the final file (so that if one gets left behind by a crash, "rm *.mod" still cleans it up). `mkstemps()` creates file with 0600 permissions so try to change it to what it would have been if we just wrote the file. Change module file reading to only read the file once; we used to read it to verify the checksum and then again to parse it. Instead, change `Parsing` so that we can get the file contents after `Prescan()` and use that to verify the checksum. Also, it has a mechanism for searching directories for files, so make use of that instead of duplicating that functionality in `ModFileReader`. This requires some changes to how errors are returned so they can be reported in the right place. Original-commit: flang-compiler/f18@d0d54971a5547820f8ed0271eb9818557bc8bc82 Reviewed-on: https://github.com/flang-compiler/f18/pull/758 Tree-same-pre-rewrite: false
2019-09-24 08:10:58 +08:00
class Message;
class MessageFixedText;
} // namespace Fortran::parser
namespace llvm {
class raw_ostream;
}
namespace Fortran::semantics {
using SourceName = parser::CharBlock;
class Symbol;
class Scope;
class SemanticsContext;
class ModFileWriter {
public:
explicit ModFileWriter(SemanticsContext &context) : context_{context} {}
bool WriteAll();
private:
SemanticsContext &context_;
// Buffer to use with raw_string_ostream
std::string usesBuf_;
std::string useExtraAttrsBuf_;
std::string declsBuf_;
std::string containsBuf_;
llvm::raw_string_ostream uses_{usesBuf_};
llvm::raw_string_ostream useExtraAttrs_{
useExtraAttrsBuf_}; // attrs added to used entity
llvm::raw_string_ostream decls_{declsBuf_};
llvm::raw_string_ostream contains_{containsBuf_};
void WriteAll(const Scope &);
void WriteOne(const Scope &);
void Write(const Symbol &);
std::string GetAsString(const Symbol &);
// Returns true if a derived type with bindings and "contains" was emitted
bool PutSymbols(const Scope &);
void PutSymbol(llvm::raw_ostream &, const Symbol &);
void PutDerivedType(const Symbol &);
void PutSubprogram(const Symbol &);
void PutGeneric(const Symbol &);
void PutUse(const Symbol &);
void PutUseExtraAttr(Attr, const Symbol &, const Symbol &);
};
class ModFileReader {
public:
// directories specifies where to search for module files
ModFileReader(SemanticsContext &context) : context_{context} {}
// Find and read the module file for a module or submodule.
// If ancestor is specified, look for a submodule of that module.
// Return the Scope for that module/submodule or nullptr on error.
Scope *Read(const SourceName &, Scope *ancestor = nullptr);
private:
SemanticsContext &context_;
[flang] Improve module file reading and writing Fix problems with writing a mod file while another compilation is reading or writing. Write to a temp and then rename it: - compute the new contents of the .mod file - if it already exists, check if it is already correct - if not, write new contents to a temp file - rename the temp to the final destination `mkstemps()` seems to be the best way to create the temp file. It returns a file descriptor, so change the rest of the mod file writing to use POSIX open/read/write/close. This seems to set errno more reliably too. There is some extra work around creating the temp to make it have the same directory and suffix as the final file (so that if one gets left behind by a crash, "rm *.mod" still cleans it up). `mkstemps()` creates file with 0600 permissions so try to change it to what it would have been if we just wrote the file. Change module file reading to only read the file once; we used to read it to verify the checksum and then again to parse it. Instead, change `Parsing` so that we can get the file contents after `Prescan()` and use that to verify the checksum. Also, it has a mechanism for searching directories for files, so make use of that instead of duplicating that functionality in `ModFileReader`. This requires some changes to how errors are returned so they can be reported in the right place. Original-commit: flang-compiler/f18@d0d54971a5547820f8ed0271eb9818557bc8bc82 Reviewed-on: https://github.com/flang-compiler/f18/pull/758 Tree-same-pre-rewrite: false
2019-09-24 08:10:58 +08:00
parser::Message &Say(const SourceName &, const std::string &,
parser::MessageFixedText &&, const std::string &);
};
} // namespace Fortran::semantics
#endif