CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
444 lines
15 KiB
C++
444 lines
15 KiB
C++
//===-- InternalNames.cpp -------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Optimizer/Support/InternalNames.h"
|
|
#include "flang/Optimizer/Dialect/FIRType.h"
|
|
#include "mlir/IR/BuiltinTypes.h"
|
|
#include "mlir/IR/Diagnostics.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include <optional>
|
|
#include <regex>
|
|
|
|
static llvm::cl::opt<std::string> mainEntryName(
|
|
"main-entry-name",
|
|
llvm::cl::desc("override the name of the default PROGRAM entry (may be "
|
|
"helpful for using other runtimes)"));
|
|
|
|
constexpr std::int64_t badValue = -1;
|
|
|
|
inline std::string prefix() { return "_Q"; }
|
|
|
|
/// Generate a mangling prefix from module, submodule, procedure, and
|
|
/// statement function names, plus an (innermost) block scope id.
|
|
static std::string doAncestors(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId = 0) {
|
|
std::string prefix;
|
|
const char *tag = "M";
|
|
for (auto mod : modules) {
|
|
prefix.append(tag).append(mod.lower());
|
|
tag = "S";
|
|
}
|
|
for (auto proc : procs)
|
|
prefix.append("F").append(proc.lower());
|
|
if (blockId)
|
|
prefix.append("B").append(std::to_string(blockId));
|
|
return prefix;
|
|
}
|
|
|
|
inline llvm::SmallVector<llvm::StringRef>
|
|
convertToStringRef(llvm::ArrayRef<std::string> from) {
|
|
return {from.begin(), from.end()};
|
|
}
|
|
|
|
inline std::optional<llvm::StringRef>
|
|
convertToStringRef(const std::optional<std::string> &from) {
|
|
std::optional<llvm::StringRef> to;
|
|
if (from)
|
|
to = *from;
|
|
return to;
|
|
}
|
|
|
|
static std::string readName(llvm::StringRef uniq, std::size_t &i,
|
|
std::size_t init, std::size_t end) {
|
|
// Allow 'X' to be part of the mangled name, which
|
|
// can happen after the special symbols are replaced
|
|
// in the mangled names by CompilerGeneratedNamesConversionPass.
|
|
for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z' || uniq[i] == 'X');
|
|
++i) {
|
|
// do nothing
|
|
}
|
|
return uniq.substr(init, i - init).str();
|
|
}
|
|
|
|
static std::int64_t readInt(llvm::StringRef uniq, std::size_t &i,
|
|
std::size_t init, std::size_t end) {
|
|
for (i = init; i < end && uniq[i] >= '0' && uniq[i] <= '9'; ++i) {
|
|
// do nothing
|
|
}
|
|
std::int64_t result = badValue;
|
|
if (uniq.substr(init, i - init).getAsInteger(10, result))
|
|
return badValue;
|
|
return result;
|
|
}
|
|
|
|
std::string fir::NameUniquer::toLower(llvm::StringRef name) {
|
|
return name.lower();
|
|
}
|
|
|
|
std::string fir::NameUniquer::intAsString(std::int64_t i) {
|
|
assert(i >= 0);
|
|
return std::to_string(i);
|
|
}
|
|
|
|
std::string fir::NameUniquer::doKind(std::int64_t kind) {
|
|
std::string result = "K";
|
|
if (kind < 0)
|
|
return result.append("N").append(intAsString(-kind));
|
|
return result.append(intAsString(kind));
|
|
}
|
|
|
|
std::string fir::NameUniquer::doKinds(llvm::ArrayRef<std::int64_t> kinds) {
|
|
std::string result;
|
|
for (auto i : kinds)
|
|
result.append(doKind(i));
|
|
return result;
|
|
}
|
|
|
|
std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) {
|
|
return prefix().append("C").append(toLower(name));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("EC")
|
|
.append(toLower(name));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name,
|
|
llvm::ArrayRef<std::int64_t> kinds) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("DT")
|
|
.append(toLower(name))
|
|
.append(doKinds(kinds));
|
|
}
|
|
|
|
std::string fir::NameUniquer::doGenerated(llvm::StringRef name) {
|
|
return prefix().append("Q").append(name);
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doGenerated(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name) {
|
|
return prefix()
|
|
.append("Q")
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append(name);
|
|
}
|
|
|
|
std::string fir::NameUniquer::doIntrinsicTypeDescriptor(
|
|
llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs, std::int64_t blockId,
|
|
IntrinsicType type, std::int64_t kind) {
|
|
const char *name = nullptr;
|
|
switch (type) {
|
|
case IntrinsicType::CHARACTER:
|
|
name = "character";
|
|
break;
|
|
case IntrinsicType::COMPLEX:
|
|
name = "complex";
|
|
break;
|
|
case IntrinsicType::INTEGER:
|
|
name = "integer";
|
|
break;
|
|
case IntrinsicType::LOGICAL:
|
|
name = "logical";
|
|
break;
|
|
case IntrinsicType::REAL:
|
|
name = "real";
|
|
break;
|
|
}
|
|
assert(name && "unknown intrinsic type");
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("YI")
|
|
.append(name)
|
|
.append(doKind(kind));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
llvm::StringRef name) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs))
|
|
.append("P")
|
|
.append(toLower(name));
|
|
}
|
|
|
|
std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name,
|
|
llvm::ArrayRef<std::int64_t> kinds) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("T")
|
|
.append(toLower(name))
|
|
.append(doKinds(kinds));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name,
|
|
llvm::ArrayRef<std::int64_t> kinds) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("CT")
|
|
.append(toLower(name))
|
|
.append(doKinds(kinds));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<std::string> modules,
|
|
llvm::ArrayRef<std::string> procs,
|
|
std::int64_t blockId, llvm::StringRef name,
|
|
llvm::ArrayRef<std::int64_t> kinds) {
|
|
auto rmodules = convertToStringRef(modules);
|
|
auto rprocs = convertToStringRef(procs);
|
|
return doTypeDescriptor(rmodules, rprocs, blockId, name, kinds);
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
std::int64_t blockId, llvm::StringRef name) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs, blockId))
|
|
.append("E")
|
|
.append(toLower(name));
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
|
|
llvm::ArrayRef<llvm::StringRef> procs,
|
|
llvm::StringRef name) {
|
|
return prefix()
|
|
.append(doAncestors(modules, procs))
|
|
.append("N")
|
|
.append(toLower(name));
|
|
}
|
|
|
|
llvm::StringRef fir::NameUniquer::doProgramEntry() {
|
|
if (mainEntryName.size())
|
|
return mainEntryName;
|
|
return "_QQmain";
|
|
}
|
|
|
|
std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName>
|
|
fir::NameUniquer::deconstruct(llvm::StringRef uniq) {
|
|
uniq = fir::NameUniquer::dropTypeConversionMarkers(uniq);
|
|
if (uniq.starts_with("_Q")) {
|
|
llvm::SmallVector<std::string> modules;
|
|
llvm::SmallVector<std::string> procs;
|
|
std::int64_t blockId = 0;
|
|
std::string name;
|
|
llvm::SmallVector<std::int64_t> kinds;
|
|
NameKind nk = NameKind::NOT_UNIQUED;
|
|
for (std::size_t i = 2, end{uniq.size()}; i != end;) {
|
|
switch (uniq[i]) {
|
|
case 'B': // Block
|
|
blockId = readInt(uniq, i, i + 1, end);
|
|
break;
|
|
case 'C': // Common block
|
|
nk = NameKind::COMMON;
|
|
name = readName(uniq, i, i + 1, end);
|
|
break;
|
|
case 'D': // Dispatch table
|
|
nk = NameKind::DISPATCH_TABLE;
|
|
assert(uniq[i + 1] == 'T');
|
|
name = readName(uniq, i, i + 2, end);
|
|
break;
|
|
case 'E':
|
|
if (uniq[i + 1] == 'C') { // Constant Entity
|
|
nk = NameKind::CONSTANT;
|
|
name = readName(uniq, i, i + 2, end);
|
|
} else { // variable Entity
|
|
nk = NameKind::VARIABLE;
|
|
name = readName(uniq, i, i + 1, end);
|
|
}
|
|
break;
|
|
case 'F': // procedure/Function ancestor component of a mangled prefix
|
|
procs.push_back(readName(uniq, i, i + 1, end));
|
|
break;
|
|
case 'K':
|
|
if (uniq[i + 1] == 'N') // Negative Kind
|
|
kinds.push_back(-readInt(uniq, i, i + 2, end));
|
|
else // [positive] Kind
|
|
kinds.push_back(readInt(uniq, i, i + 1, end));
|
|
break;
|
|
case 'M': // Module
|
|
case 'S': // Submodule
|
|
modules.push_back(readName(uniq, i, i + 1, end));
|
|
break;
|
|
case 'N': // Namelist group
|
|
nk = NameKind::NAMELIST_GROUP;
|
|
name = readName(uniq, i, i + 1, end);
|
|
break;
|
|
case 'P': // Procedure/function (itself)
|
|
nk = NameKind::PROCEDURE;
|
|
name = readName(uniq, i, i + 1, end);
|
|
break;
|
|
case 'Q': // UniQue mangle name tag
|
|
nk = NameKind::GENERATED;
|
|
name = uniq;
|
|
i = end;
|
|
break;
|
|
case 'T': // derived Type
|
|
nk = NameKind::DERIVED_TYPE;
|
|
name = readName(uniq, i, i + 1, end);
|
|
break;
|
|
case 'Y':
|
|
if (uniq[i + 1] == 'I') { // tYpe descriptor for an Intrinsic type
|
|
nk = NameKind::INTRINSIC_TYPE_DESC;
|
|
name = readName(uniq, i, i + 1, end);
|
|
} else { // tYpe descriptor
|
|
nk = NameKind::TYPE_DESC;
|
|
name = readName(uniq, i, i + 2, end);
|
|
}
|
|
break;
|
|
default:
|
|
assert(false && "unknown uniquing code");
|
|
break;
|
|
}
|
|
}
|
|
return {nk, DeconstructedName(modules, procs, blockId, name, kinds)};
|
|
}
|
|
return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)};
|
|
}
|
|
|
|
bool fir::NameUniquer::isExternalFacingUniquedName(
|
|
const std::pair<fir::NameUniquer::NameKind,
|
|
fir::NameUniquer::DeconstructedName> &deconstructResult) {
|
|
return (deconstructResult.first == NameKind::PROCEDURE ||
|
|
deconstructResult.first == NameKind::COMMON) &&
|
|
deconstructResult.second.modules.empty() &&
|
|
deconstructResult.second.procs.empty();
|
|
}
|
|
|
|
bool fir::NameUniquer::needExternalNameMangling(llvm::StringRef uniquedName) {
|
|
auto result = fir::NameUniquer::deconstruct(uniquedName);
|
|
return result.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&
|
|
fir::NameUniquer::isExternalFacingUniquedName(result);
|
|
}
|
|
|
|
bool fir::NameUniquer::belongsToModule(llvm::StringRef uniquedName,
|
|
llvm::StringRef moduleName) {
|
|
auto result = fir::NameUniquer::deconstruct(uniquedName);
|
|
return !result.second.modules.empty() &&
|
|
result.second.modules[0] == moduleName;
|
|
}
|
|
|
|
/// Flang records the lexical module/submodule nesting of a symbol in the
|
|
/// uniqued root produced by \c fir::NameUniquer; \c deconstruct exposes that
|
|
/// as \c parts.modules. A non-empty module path means the symbol was declared
|
|
/// under a module or submodule, not only at program or internal unit scope.
|
|
/// Procedure nesting is encoded as \c F<proc> ancestors in \c parts.procs;
|
|
/// those must be empty so we do not classify locals inside module procedures
|
|
/// (including \c SAVE locals) as module-scope data.
|
|
/// We then require \c VARIABLE, \c CONSTANT, or \c COMMON so we match
|
|
/// module-level data (including common), not procedures or other name kinds
|
|
/// that can also carry a module prefix.
|
|
bool fir::NameUniquer::isModuleScopeDataUniquedName(
|
|
llvm::StringRef uniquedName) {
|
|
auto [kind, parts] = fir::NameUniquer::deconstruct(uniquedName);
|
|
if (parts.modules.empty() || !parts.procs.empty())
|
|
return false;
|
|
|
|
switch (kind) {
|
|
case fir::NameUniquer::NameKind::VARIABLE:
|
|
case fir::NameUniquer::NameKind::CONSTANT:
|
|
case fir::NameUniquer::NameKind::COMMON:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static std::string
|
|
mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) {
|
|
if (kinds.empty())
|
|
return "";
|
|
std::string result;
|
|
for (std::int64_t kind : kinds)
|
|
result += (fir::kNameSeparator + std::to_string(kind)).str();
|
|
return result;
|
|
}
|
|
|
|
static std::string getDerivedTypeObjectName(llvm::StringRef mangledTypeName,
|
|
const llvm::StringRef separator) {
|
|
mangledTypeName =
|
|
fir::NameUniquer::dropTypeConversionMarkers(mangledTypeName);
|
|
auto result = fir::NameUniquer::deconstruct(mangledTypeName);
|
|
if (result.first != fir::NameUniquer::NameKind::DERIVED_TYPE)
|
|
return "";
|
|
std::string varName = separator.str() + result.second.name +
|
|
mangleTypeDescriptorKinds(result.second.kinds);
|
|
llvm::SmallVector<llvm::StringRef> modules;
|
|
for (const std::string &mod : result.second.modules)
|
|
modules.push_back(mod);
|
|
llvm::SmallVector<llvm::StringRef> procs;
|
|
for (const std::string &proc : result.second.procs)
|
|
procs.push_back(proc);
|
|
return fir::NameUniquer::doVariable(modules, procs, result.second.blockId,
|
|
varName);
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) {
|
|
return getDerivedTypeObjectName(mangledTypeName,
|
|
fir::kTypeDescriptorSeparator);
|
|
}
|
|
|
|
std::string fir::NameUniquer::getTypeDescriptorAssemblyName(
|
|
llvm::StringRef mangledTypeName) {
|
|
return replaceSpecialSymbols(getTypeDescriptorName(mangledTypeName));
|
|
}
|
|
|
|
std::string fir::NameUniquer::getTypeDescriptorBindingTableName(
|
|
llvm::StringRef mangledTypeName) {
|
|
return getDerivedTypeObjectName(mangledTypeName, fir::kBindingTableSeparator);
|
|
}
|
|
|
|
std::string
|
|
fir::NameUniquer::getComponentInitName(llvm::StringRef mangledTypeName,
|
|
llvm::StringRef componentName) {
|
|
|
|
std::string prefix =
|
|
getDerivedTypeObjectName(mangledTypeName, fir::kComponentInitSeparator);
|
|
return (prefix + fir::kNameSeparator + componentName).str();
|
|
}
|
|
|
|
llvm::StringRef
|
|
fir::NameUniquer::dropTypeConversionMarkers(llvm::StringRef mangledTypeName) {
|
|
if (mangledTypeName.ends_with(fir::boxprocSuffix))
|
|
return mangledTypeName.drop_back(fir::boxprocSuffix.size());
|
|
return mangledTypeName;
|
|
}
|
|
|
|
std::string fir::NameUniquer::replaceSpecialSymbols(const std::string &name) {
|
|
return std::regex_replace(name, std::regex{"\\."}, "X");
|
|
}
|
|
|
|
bool fir::NameUniquer::isSpecialSymbol(llvm::StringRef name) {
|
|
return !name.empty() && (name[0] == '.' || name[0] == 'X');
|
|
}
|