| //===-- 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" |
| |
| 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"; } |
| |
| static std::string doModules(llvm::ArrayRef<llvm::StringRef> mods) { |
| std::string result; |
| auto *token = "M"; |
| for (auto mod : mods) { |
| result.append(token).append(mod.lower()); |
| token = "S"; |
| } |
| return result; |
| } |
| |
| static std::string doModulesHost(llvm::ArrayRef<llvm::StringRef> mods, |
| llvm::Optional<llvm::StringRef> host) { |
| std::string result = doModules(mods); |
| if (host.hasValue()) |
| result.append("F").append(host->lower()); |
| return result; |
| } |
| |
| inline llvm::SmallVector<llvm::StringRef, 2> |
| convertToStringRef(llvm::ArrayRef<std::string> from) { |
| return {from.begin(), from.end()}; |
| } |
| |
| inline llvm::Optional<llvm::StringRef> |
| convertToStringRef(const llvm::Optional<std::string> &from) { |
| llvm::Optional<llvm::StringRef> to; |
| if (from.hasValue()) |
| to = from.getValue(); |
| return to; |
| } |
| |
| static std::string readName(llvm::StringRef uniq, std::size_t &i, |
| std::size_t init, std::size_t end) { |
| for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z'); ++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) { |
| std::string result = prefix(); |
| return result.append("B").append(toLower(name)); |
| } |
| |
| std::string fir::NameUniquer::doBlockData(llvm::StringRef name) { |
| std::string result = prefix(); |
| return result.append("L").append(toLower(name)); |
| } |
| |
| std::string |
| fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("EC"); |
| return result.append(toLower(name)); |
| } |
| |
| std::string |
| fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name, |
| llvm::ArrayRef<std::int64_t> kinds) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("DT"); |
| return result.append(toLower(name)).append(doKinds(kinds)); |
| } |
| |
| std::string fir::NameUniquer::doGenerated(llvm::StringRef name) { |
| std::string result = prefix(); |
| return result.append("Q").append(name); |
| } |
| |
| std::string fir::NameUniquer::doIntrinsicTypeDescriptor( |
| llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, 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"); |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("C"); |
| return result.append(name).append(doKind(kind)); |
| } |
| |
| std::string |
| fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("P"); |
| return result.append(toLower(name)); |
| } |
| |
| std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name, |
| llvm::ArrayRef<std::int64_t> kinds) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("T"); |
| return result.append(toLower(name)).append(doKinds(kinds)); |
| } |
| |
| std::string |
| fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name, |
| llvm::ArrayRef<std::int64_t> kinds) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("CT"); |
| return result.append(toLower(name)).append(doKinds(kinds)); |
| } |
| |
| std::string fir::NameUniquer::doTypeDescriptor( |
| llvm::ArrayRef<std::string> modules, llvm::Optional<std::string> host, |
| llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds) { |
| auto rmodules = convertToStringRef(modules); |
| auto rhost = convertToStringRef(host); |
| return doTypeDescriptor(rmodules, rhost, name, kinds); |
| } |
| |
| std::string |
| fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("E"); |
| return result.append(toLower(name)); |
| } |
| |
| std::string |
| fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules, |
| llvm::Optional<llvm::StringRef> host, |
| llvm::StringRef name) { |
| std::string result = prefix(); |
| result.append(doModulesHost(modules, host)).append("G"); |
| return result.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) { |
| if (uniq.startswith("_Q")) { |
| llvm::SmallVector<std::string> modules; |
| llvm::Optional<std::string> host; |
| 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': |
| nk = NameKind::COMMON; |
| name = readName(uniq, i, i + 1, end); |
| break; |
| case 'C': |
| if (uniq[i + 1] == 'T') { |
| nk = NameKind::TYPE_DESC; |
| name = readName(uniq, i, i + 2, end); |
| } else { |
| nk = NameKind::INTRINSIC_TYPE_DESC; |
| name = readName(uniq, i, i + 1, end); |
| } |
| break; |
| case 'D': |
| nk = NameKind::DISPATCH_TABLE; |
| assert(uniq[i + 1] == 'T'); |
| name = readName(uniq, i, i + 2, end); |
| break; |
| case 'E': |
| if (uniq[i + 1] == 'C') { |
| nk = NameKind::CONSTANT; |
| name = readName(uniq, i, i + 2, end); |
| } else { |
| nk = NameKind::VARIABLE; |
| name = readName(uniq, i, i + 1, end); |
| } |
| break; |
| case 'L': |
| nk = NameKind::BLOCK_DATA_NAME; |
| name = readName(uniq, i, i + 1, end); |
| break; |
| case 'P': |
| nk = NameKind::PROCEDURE; |
| name = readName(uniq, i, i + 1, end); |
| break; |
| case 'Q': |
| nk = NameKind::GENERATED; |
| name = uniq; |
| i = end; |
| break; |
| case 'T': |
| nk = NameKind::DERIVED_TYPE; |
| name = readName(uniq, i, i + 1, end); |
| break; |
| |
| case 'M': |
| case 'S': |
| modules.push_back(readName(uniq, i, i + 1, end)); |
| break; |
| case 'F': |
| host = readName(uniq, i, i + 1, end); |
| break; |
| case 'K': |
| if (uniq[i + 1] == 'N') |
| kinds.push_back(-readInt(uniq, i, i + 2, end)); |
| else |
| kinds.push_back(readInt(uniq, i, i + 1, end)); |
| break; |
| case 'G': |
| nk = NameKind::NAMELIST_GROUP; |
| name = readName(uniq, i, i + 1, end); |
| break; |
| |
| default: |
| assert(false && "unknown uniquing code"); |
| break; |
| } |
| } |
| return {nk, DeconstructedName(modules, host, 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.host; |
| } |
| |
| 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); |
| } |