//===-- 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 // //===----------------------------------------------------------------------===// #include "flang/Optimizer/Support/InternalNames.h" #include "mlir/IR/Diagnostics.h" #include "llvm/Support/CommandLine.h" static llvm::cl::opt 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 BAD_VALUE = -1; inline std::string prefix() { return "_Q"; } static std::string doModules(llvm::ArrayRef 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 mods, llvm::Optional host) { std::string result = doModules(mods); if (host.hasValue()) result.append("F").append(host->lower()); return result; } inline llvm::SmallVector convertToStringRef(llvm::ArrayRef from) { return {from.begin(), from.end()}; } inline llvm::Optional convertToStringRef(const llvm::Optional &from) { llvm::Optional 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 = BAD_VALUE; if (uniq.substr(init, i - init).getAsInteger(10, result)) return BAD_VALUE; 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 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::doConstant(llvm::ArrayRef modules, llvm::Optional 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 modules, llvm::Optional host, llvm::StringRef name, llvm::ArrayRef 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 modules, llvm::Optional 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 modules, llvm::Optional 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 modules, llvm::Optional host, llvm::StringRef name, llvm::ArrayRef 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 modules, llvm::Optional host, llvm::StringRef name, llvm::ArrayRef 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 modules, llvm::Optional host, llvm::StringRef name, llvm::ArrayRef kinds) { auto rmodules = convertToStringRef(modules); auto rhost = convertToStringRef(host); return doTypeDescriptor(rmodules, rhost, name, kinds); } std::string fir::NameUniquer::doVariable(llvm::ArrayRef modules, llvm::Optional host, llvm::StringRef name) { std::string result = prefix(); result.append(doModulesHost(modules, host)).append("E"); return result.append(toLower(name)); } llvm::StringRef fir::NameUniquer::doProgramEntry() { if (mainEntryName.size()) return mainEntryName; return "_QQmain"; } std::pair fir::NameUniquer::deconstruct(llvm::StringRef uniq) { if (uniq.startswith("_Q")) { llvm::SmallVector modules; llvm::Optional host; std::string name; llvm::SmallVector 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 '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; default: assert(false && "unknown uniquing code"); break; } } return {nk, DeconstructedName(modules, host, name, kinds)}; } return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)}; }