Skip to content

Commit 6ffea74

Browse files
authored
[flang] Use BIND name, if any, when consolidating common blocks (#65613)
This patch changes how common blocks are aggregated and named in lowering in order to: * fix one obvious issue where BIND(C) and non BIND(C) with the same Fortran name were "merged" * go further and deal with a derivative where the BIND(C) C name matches the assembly name of a Fortran common block. This is a bit unspecified IMHO, but gfortran, ifort, and nvfortran "merge" the common block without complaints as a linker would have done. This required getting rid of all the common block mangling early in FIR (\_QC) instead of leaving that to the phase that emits LLVM from FIR because BIND(C) common blocks did not have mangled names. Care has to be taken to deal with the underscoring option of flang-new. See added flang/test/Lower/HLFIR/common-block-bindc-conflicts.f90 for an illustration.
1 parent d4d0b5e commit 6ffea74

32 files changed

+167
-79
lines changed

flang/include/flang/Common/Fortran.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,5 +109,7 @@ std::string AsFortran(IgnoreTKRSet);
109109
bool AreCompatibleCUDADataAttrs(
110110
std::optional<CUDADataAttr>, std::optional<CUDADataAttr>, IgnoreTKRSet);
111111

112+
static constexpr char blankCommonObjectName[] = "__BLNK__";
113+
112114
} // namespace Fortran::common
113115
#endif // FORTRAN_COMMON_FORTRAN_H_

flang/include/flang/Lower/LoweringOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ ENUM_LOWERINGOPT(LowerToHighLevelFIR, unsigned, 1, 0)
3434
/// If true, reverse PowerPC native vector element order.
3535
ENUM_LOWERINGOPT(NoPPCNativeVecElemOrder, unsigned, 1, 0)
3636

37+
/// If true, assume external names will be suffixed with an underscore. On by default.
38+
ENUM_LOWERINGOPT(Underscoring, unsigned, 1, 1)
39+
3740
#undef LOWERINGOPT
3841
#undef ENUM_LOWERINGOPT

flang/include/flang/Lower/Mangler.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ using ScopeBlockIdMap =
4343
/// a symbol where all the Fortran context is needed. Otherwise, external
4444
/// symbols are mangled outside of any scope.
4545
std::string mangleName(const semantics::Symbol &, ScopeBlockIdMap &,
46-
bool keepExternalInScope = false);
46+
bool keepExternalInScope = false,
47+
bool underscoring = true);
4748
std::string mangleName(const semantics::Symbol &,
48-
bool keepExternalInScope = false);
49+
bool keepExternalInScope = false,
50+
bool underscoring = true);
4951

5052
/// Convert a derived type instance to an internal name.
5153
std::string mangleName(const semantics::DerivedTypeSpec &, ScopeBlockIdMap &);

flang/include/flang/Semantics/semantics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class SemanticsContext {
9393
}
9494
const std::string &moduleDirectory() const { return moduleDirectory_; }
9595
const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
96+
bool underscoring() const { return underscoring_; }
9697
bool warningsAreErrors() const { return warningsAreErrors_; }
9798
bool debugModuleWriter() const { return debugModuleWriter_; }
9899
const evaluate::IntrinsicProcTable &intrinsics() const { return intrinsics_; }
@@ -130,6 +131,10 @@ class SemanticsContext {
130131
moduleFileSuffix_ = x;
131132
return *this;
132133
}
134+
SemanticsContext &set_underscoring(bool x) {
135+
underscoring_ = x;
136+
return *this;
137+
}
133138
SemanticsContext &set_warnOnNonstandardUsage(bool x) {
134139
warnOnNonstandardUsage_ = x;
135140
return *this;
@@ -262,6 +267,7 @@ class SemanticsContext {
262267
std::vector<std::string> intrinsicModuleDirectories_;
263268
std::string moduleDirectory_{"."s};
264269
std::string moduleFileSuffix_{".mod"};
270+
bool underscoring_{true};
265271
bool warnOnNonstandardUsage_{false};
266272
bool warningsAreErrors_{false};
267273
bool debugModuleWriter_{false};

flang/include/flang/Semantics/tools.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,5 +683,8 @@ std::optional<R> GetConstExpr(
683683
// Returns "m" for a module, "m:sm" for a submodule.
684684
std::string GetModuleOrSubmoduleName(const Symbol &);
685685

686+
// Return the assembly name emitted for a common block.
687+
std::string GetCommonBlockObjectName(const Symbol &, bool underscoring);
688+
686689
} // namespace Fortran::semantics
687690
#endif // FORTRAN_SEMANTICS_TOOLS_H_

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,8 @@ void CompilerInvocation::setSemanticsOpts(
12371237
.set_searchDirectories(fortranOptions.searchDirectories)
12381238
.set_intrinsicModuleDirectories(fortranOptions.intrinsicModuleDirectories)
12391239
.set_warningsAreErrors(getWarnAsErr())
1240-
.set_moduleFileSuffix(getModuleFileSuffix());
1240+
.set_moduleFileSuffix(getModuleFileSuffix())
1241+
.set_underscoring(getCodeGenOpts().Underscoring);
12411242

12421243
llvm::Triple targetTriple{llvm::Triple(this->targetOpts.triple)};
12431244
// FIXME: Handle real(3) ?
@@ -1262,6 +1263,7 @@ void CompilerInvocation::setLoweringOptions() {
12621263

12631264
// Lower TRANSPOSE as a runtime call under -O0.
12641265
loweringOpts.setOptimizeTranspose(codegenOpts.OptimizationLevel > 0);
1266+
loweringOpts.setUnderscoring(codegenOpts.Underscoring);
12651267

12661268
const LangOptions &langOptions = getLangOpts();
12671269
Fortran::common::MathOptionsBase &mathOpts = loweringOpts.getMathOptions();

flang/lib/Lower/Bridge.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
836836
}
837837
std::string
838838
mangleName(const Fortran::semantics::Symbol &symbol) override final {
839-
return Fortran::lower::mangle::mangleName(symbol, scopeBlockIdMap);
839+
return Fortran::lower::mangle::mangleName(
840+
symbol, scopeBlockIdMap, /*keepExternalInScope=*/false,
841+
getLoweringOptions().getUnderscoring());
840842
}
841843
std::string mangleName(
842844
const Fortran::semantics::DerivedTypeSpec &derivedType) override final {

flang/lib/Lower/Mangler.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,9 @@ Fortran::lower::mangle::mangleName(std::string &name,
8383
}
8484

8585
// Mangle the name of \p symbol to make it globally unique.
86-
std::string
87-
Fortran::lower::mangle::mangleName(const Fortran::semantics::Symbol &symbol,
88-
ScopeBlockIdMap &scopeBlockIdMap,
89-
bool keepExternalInScope) {
86+
std::string Fortran::lower::mangle::mangleName(
87+
const Fortran::semantics::Symbol &symbol, ScopeBlockIdMap &scopeBlockIdMap,
88+
bool keepExternalInScope, bool underscoring) {
9089
// Resolve module and host associations before mangling.
9190
const auto &ultimateSymbol = symbol.GetUltimate();
9291

@@ -167,11 +166,12 @@ Fortran::lower::mangle::mangleName(const Fortran::semantics::Symbol &symbol,
167166
symbolName);
168167
},
169168
[&](const Fortran::semantics::CommonBlockDetails &) {
170-
return fir::NameUniquer::doCommonBlock(symbolName);
169+
return Fortran::semantics::GetCommonBlockObjectName(ultimateSymbol,
170+
underscoring);
171171
},
172172
[&](const Fortran::semantics::ProcBindingDetails &procBinding) {
173173
return mangleName(procBinding.symbol(), scopeBlockIdMap,
174-
keepExternalInScope);
174+
keepExternalInScope, underscoring);
175175
},
176176
[&](const Fortran::semantics::DerivedTypeDetails &) -> std::string {
177177
// Derived type mangling must use mangleName(DerivedTypeSpec) so
@@ -186,13 +186,14 @@ Fortran::lower::mangle::mangleName(const Fortran::semantics::Symbol &symbol,
186186

187187
std::string
188188
Fortran::lower::mangle::mangleName(const Fortran::semantics::Symbol &symbol,
189-
bool keepExternalInScope) {
189+
bool keepExternalInScope,
190+
bool underscoring) {
190191
assert((symbol.owner().kind() !=
191192
Fortran::semantics::Scope::Kind::BlockConstruct ||
192193
symbol.has<Fortran::semantics::SubprogramDetails>()) &&
193194
"block object mangling must specify a scopeBlockIdMap");
194195
ScopeBlockIdMap scopeBlockIdMap;
195-
return mangleName(symbol, scopeBlockIdMap, keepExternalInScope);
196+
return mangleName(symbol, scopeBlockIdMap, keepExternalInScope, underscoring);
196197
}
197198

198199
std::string Fortran::lower::mangle::mangleName(

flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "flang/Common/Fortran.h"
910
#include "flang/Optimizer/Dialect/FIRDialect.h"
1011
#include "flang/Optimizer/Dialect/FIROps.h"
1112
#include "flang/Optimizer/Support/InternalNames.h"
@@ -36,7 +37,7 @@ mangleExternalName(const std::pair<fir::NameUniquer::NameKind,
3637
bool appendUnderscore) {
3738
if (result.first == fir::NameUniquer::NameKind::COMMON &&
3839
result.second.name.empty())
39-
return "__BLNK__";
40+
return Fortran::common::blankCommonObjectName;
4041

4142
if (appendUnderscore)
4243
return result.second.name + "_";

flang/lib/Semantics/semantics.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,14 @@ class CommonBlockMap {
212212
void MapCommonBlockAndCheckConflicts(
213213
SemanticsContext &context, const Symbol &common) {
214214
const Symbol *isInitialized{CommonBlockIsInitialized(common)};
215-
auto [it, firstAppearance] = commonBlocks_.insert({common.name(),
215+
// Merge common according to the name they will have in the object files.
216+
// This allows merging BIND(C) and non BIND(C) common block instead of
217+
// later crashing. This "merge" matches what ifort/gfortran/nvfortran are
218+
// doing and what a linker would do if the definition were in distinct
219+
// files.
220+
std::string commonName{
221+
GetCommonBlockObjectName(common, context.underscoring())};
222+
auto [it, firstAppearance] = commonBlocks_.insert({commonName,
216223
isInitialized ? CommonBlockInfo{common, common}
217224
: CommonBlockInfo{common, std::nullopt}});
218225
if (!firstAppearance) {
@@ -291,7 +298,8 @@ class CommonBlockMap {
291298
}
292299
return nullptr;
293300
}
294-
std::map<SourceName, CommonBlockInfo> commonBlocks_;
301+
302+
std::map<std::string, CommonBlockInfo> commonBlocks_;
295303
};
296304

297305
SemanticsContext::SemanticsContext(

0 commit comments

Comments
 (0)