Skip to content

Commit 2fea7be

Browse files
committed
[flang] Use module file hashes for more checking and disambiguation
f18's module files are Fortran with a leading header comment containing the module file format version and a hash of the following contents. This hash is currently used only to protect module files against corruption and truncation. Extend the use of these hashes to catch or avoid some error cases. When one module file depends upon another, note its hash in additional module file header comments. This allows the compiler to detect when the module dependency is on a module file that has been updated. Further, it allows the compiler to find the right module file dependency when the same module file name appears in multiple directories on the module search path. The order in which module files are written, when multiple modules appear in a source file, is such that every dependency is written before the module(s) that depend upon it, so that their hashes are known. A warning is emitted when a module file is not the first hit on the module file search path. Further work is needed to add a compiler option that emits (larger) stand-alone module files that incorporate copies of their dependencies rather than relying on search paths. This will be desirable for application libraries that want to ship only "top-level" module files without needing to include their dependencies. Another future work item would be to admit multiple modules in the same compilation with the same name if they have distinct hashes.
1 parent b629414 commit 2fea7be

17 files changed

+300
-41
lines changed

flang/include/flang/Parser/source.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace Fortran::parser {
3636
std::string DirectoryName(std::string path);
3737
std::optional<std::string> LocateSourceFile(
3838
std::string name, const std::list<std::string> &searchPath);
39+
std::vector<std::string> LocateSourceFileAll(
40+
std::string name, const std::vector<std::string> &searchPath);
3941

4042
class SourceFile;
4143

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===-- include/flang/Semantics/module-dependences.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_SEMANTICS_MODULE_DEPENDENCES_H_
10+
#define FORTRAN_SEMANTICS_MODULE_DEPENDENCES_H_
11+
12+
#include <cinttypes>
13+
#include <map>
14+
#include <optional>
15+
#include <string>
16+
17+
namespace Fortran::semantics {
18+
19+
using ModuleCheckSumType = std::uint64_t;
20+
21+
class ModuleDependences {
22+
public:
23+
void AddDependence(std::string &&name, ModuleCheckSumType hash) {
24+
map_.emplace(std::move(name), hash);
25+
}
26+
std::optional<ModuleCheckSumType> GetRequiredHash(const std::string &name) {
27+
if (auto iter{map_.find(name)}; iter != map_.end()) {
28+
return iter->second;
29+
} else {
30+
return std::nullopt;
31+
}
32+
}
33+
34+
private:
35+
std::map<std::string, ModuleCheckSumType> map_;
36+
};
37+
38+
} // namespace Fortran::semantics
39+
#endif // FORTRAN_SEMANTICS_MODULE_DEPENDENCES_H_

flang/include/flang/Semantics/semantics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "flang/Evaluate/intrinsics.h"
1717
#include "flang/Evaluate/target.h"
1818
#include "flang/Parser/message.h"
19+
#include "flang/Semantics/module-dependences.h"
1920
#include <iosfwd>
2021
#include <set>
2122
#include <string>
@@ -108,6 +109,7 @@ class SemanticsContext {
108109
parser::Messages &messages() { return messages_; }
109110
evaluate::FoldingContext &foldingContext() { return foldingContext_; }
110111
parser::AllCookedSources &allCookedSources() { return allCookedSources_; }
112+
ModuleDependences &moduleDependences() { return moduleDependences_; }
111113

112114
SemanticsContext &set_location(
113115
const std::optional<parser::CharBlock> &location) {
@@ -293,6 +295,7 @@ class SemanticsContext {
293295
const Scope *ppcBuiltinsScope_{nullptr}; // module __ppc_intrinsics
294296
std::list<parser::Program> modFileParseTrees_;
295297
std::unique_ptr<CommonBlockMap> commonBlockMap_;
298+
ModuleDependences moduleDependences_;
296299
};
297300

298301
class Semantics {

flang/include/flang/Semantics/symbol.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flang/Common/enum-set.h"
1515
#include "flang/Common/reference.h"
1616
#include "flang/Common/visit.h"
17+
#include "flang/Semantics/module-dependences.h"
1718
#include "llvm/ADT/DenseMapInfo.h"
1819

1920
#include <array>
@@ -86,11 +87,16 @@ class ModuleDetails : public WithOmpDeclarative {
8687
void set_scope(const Scope *);
8788
bool isDefaultPrivate() const { return isDefaultPrivate_; }
8889
void set_isDefaultPrivate(bool yes = true) { isDefaultPrivate_ = yes; }
90+
std::optional<ModuleCheckSumType> moduleFileHash() const {
91+
return moduleFileHash_;
92+
}
93+
void set_moduleFileHash(ModuleCheckSumType x) { moduleFileHash_ = x; }
8994

9095
private:
9196
bool isSubmodule_;
9297
bool isDefaultPrivate_{false};
9398
const Scope *scope_{nullptr};
99+
std::optional<ModuleCheckSumType> moduleFileHash_;
94100
};
95101

96102
class MainProgramDetails : public WithOmpDeclarative {
@@ -1035,7 +1041,7 @@ struct SymbolAddressCompare {
10351041
// Symbol comparison is usually based on the order of cooked source
10361042
// stream creation and, when both are from the same cooked source,
10371043
// their positions in that cooked source stream.
1038-
// Don't use this comparator or OrderedSymbolSet to hold
1044+
// Don't use this comparator or SourceOrderedSymbolSet to hold
10391045
// Symbols that might be subject to ReplaceName().
10401046
struct SymbolSourcePositionCompare {
10411047
// These functions are implemented in Evaluate/tools.cpp to

flang/lib/Parser/source.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,24 @@ std::optional<std::string> LocateSourceFile(
7575
return std::nullopt;
7676
}
7777

78+
std::vector<std::string> LocateSourceFileAll(
79+
std::string name, const std::vector<std::string> &searchPath) {
80+
if (name == "-" || llvm::sys::path::is_absolute(name)) {
81+
return {name};
82+
}
83+
std::vector<std::string> result;
84+
for (const std::string &dir : searchPath) {
85+
llvm::SmallString<128> path{dir};
86+
llvm::sys::path::append(path, name);
87+
bool isDir{false};
88+
auto er = llvm::sys::fs::is_directory(path, isDir);
89+
if (!er && !isDir) {
90+
result.emplace_back(path.str().str());
91+
}
92+
}
93+
return result;
94+
}
95+
7896
std::size_t RemoveCarriageReturns(llvm::MutableArrayRef<char> buf) {
7997
std::size_t wrote{0};
8098
char *buffer{buf.data()};

0 commit comments

Comments
 (0)