418 lines · cpp
1//===-- InternalNames.cpp -------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/10//11//===----------------------------------------------------------------------===//12 13#include "flang/Optimizer/Support/InternalNames.h"14#include "flang/Optimizer/Dialect/FIRType.h"15#include "mlir/IR/BuiltinTypes.h"16#include "mlir/IR/Diagnostics.h"17#include "llvm/Support/CommandLine.h"18#include <optional>19#include <regex>20 21static llvm::cl::opt<std::string> mainEntryName(22 "main-entry-name",23 llvm::cl::desc("override the name of the default PROGRAM entry (may be "24 "helpful for using other runtimes)"));25 26constexpr std::int64_t badValue = -1;27 28inline std::string prefix() { return "_Q"; }29 30/// Generate a mangling prefix from module, submodule, procedure, and31/// statement function names, plus an (innermost) block scope id.32static std::string doAncestors(llvm::ArrayRef<llvm::StringRef> modules,33 llvm::ArrayRef<llvm::StringRef> procs,34 std::int64_t blockId = 0) {35 std::string prefix;36 const char *tag = "M";37 for (auto mod : modules) {38 prefix.append(tag).append(mod.lower());39 tag = "S";40 }41 for (auto proc : procs)42 prefix.append("F").append(proc.lower());43 if (blockId)44 prefix.append("B").append(std::to_string(blockId));45 return prefix;46}47 48inline llvm::SmallVector<llvm::StringRef>49convertToStringRef(llvm::ArrayRef<std::string> from) {50 return {from.begin(), from.end()};51}52 53inline std::optional<llvm::StringRef>54convertToStringRef(const std::optional<std::string> &from) {55 std::optional<llvm::StringRef> to;56 if (from)57 to = *from;58 return to;59}60 61static std::string readName(llvm::StringRef uniq, std::size_t &i,62 std::size_t init, std::size_t end) {63 // Allow 'X' to be part of the mangled name, which64 // can happen after the special symbols are replaced65 // in the mangled names by CompilerGeneratedNamesConversionPass.66 for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z' || uniq[i] == 'X');67 ++i) {68 // do nothing69 }70 return uniq.substr(init, i - init).str();71}72 73static std::int64_t readInt(llvm::StringRef uniq, std::size_t &i,74 std::size_t init, std::size_t end) {75 for (i = init; i < end && uniq[i] >= '0' && uniq[i] <= '9'; ++i) {76 // do nothing77 }78 std::int64_t result = badValue;79 if (uniq.substr(init, i - init).getAsInteger(10, result))80 return badValue;81 return result;82}83 84std::string fir::NameUniquer::toLower(llvm::StringRef name) {85 return name.lower();86}87 88std::string fir::NameUniquer::intAsString(std::int64_t i) {89 assert(i >= 0);90 return std::to_string(i);91}92 93std::string fir::NameUniquer::doKind(std::int64_t kind) {94 std::string result = "K";95 if (kind < 0)96 return result.append("N").append(intAsString(-kind));97 return result.append(intAsString(kind));98}99 100std::string fir::NameUniquer::doKinds(llvm::ArrayRef<std::int64_t> kinds) {101 std::string result;102 for (auto i : kinds)103 result.append(doKind(i));104 return result;105}106 107std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) {108 return prefix().append("C").append(toLower(name));109}110 111std::string112fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules,113 llvm::ArrayRef<llvm::StringRef> procs,114 std::int64_t blockId, llvm::StringRef name) {115 return prefix()116 .append(doAncestors(modules, procs, blockId))117 .append("EC")118 .append(toLower(name));119}120 121std::string122fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,123 llvm::ArrayRef<llvm::StringRef> procs,124 std::int64_t blockId, llvm::StringRef name,125 llvm::ArrayRef<std::int64_t> kinds) {126 return prefix()127 .append(doAncestors(modules, procs, blockId))128 .append("DT")129 .append(toLower(name))130 .append(doKinds(kinds));131}132 133std::string fir::NameUniquer::doGenerated(llvm::StringRef name) {134 return prefix().append("Q").append(name);135}136 137std::string138fir::NameUniquer::doGenerated(llvm::ArrayRef<llvm::StringRef> modules,139 llvm::ArrayRef<llvm::StringRef> procs,140 std::int64_t blockId, llvm::StringRef name) {141 return prefix()142 .append("Q")143 .append(doAncestors(modules, procs, blockId))144 .append(name);145}146 147std::string fir::NameUniquer::doIntrinsicTypeDescriptor(148 llvm::ArrayRef<llvm::StringRef> modules,149 llvm::ArrayRef<llvm::StringRef> procs, std::int64_t blockId,150 IntrinsicType type, std::int64_t kind) {151 const char *name = nullptr;152 switch (type) {153 case IntrinsicType::CHARACTER:154 name = "character";155 break;156 case IntrinsicType::COMPLEX:157 name = "complex";158 break;159 case IntrinsicType::INTEGER:160 name = "integer";161 break;162 case IntrinsicType::LOGICAL:163 name = "logical";164 break;165 case IntrinsicType::REAL:166 name = "real";167 break;168 }169 assert(name && "unknown intrinsic type");170 return prefix()171 .append(doAncestors(modules, procs, blockId))172 .append("YI")173 .append(name)174 .append(doKind(kind));175}176 177std::string178fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules,179 llvm::ArrayRef<llvm::StringRef> procs,180 llvm::StringRef name) {181 return prefix()182 .append(doAncestors(modules, procs))183 .append("P")184 .append(toLower(name));185}186 187std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules,188 llvm::ArrayRef<llvm::StringRef> procs,189 std::int64_t blockId, llvm::StringRef name,190 llvm::ArrayRef<std::int64_t> kinds) {191 return prefix()192 .append(doAncestors(modules, procs, blockId))193 .append("T")194 .append(toLower(name))195 .append(doKinds(kinds));196}197 198std::string199fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,200 llvm::ArrayRef<llvm::StringRef> procs,201 std::int64_t blockId, llvm::StringRef name,202 llvm::ArrayRef<std::int64_t> kinds) {203 return prefix()204 .append(doAncestors(modules, procs, blockId))205 .append("CT")206 .append(toLower(name))207 .append(doKinds(kinds));208}209 210std::string211fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<std::string> modules,212 llvm::ArrayRef<std::string> procs,213 std::int64_t blockId, llvm::StringRef name,214 llvm::ArrayRef<std::int64_t> kinds) {215 auto rmodules = convertToStringRef(modules);216 auto rprocs = convertToStringRef(procs);217 return doTypeDescriptor(rmodules, rprocs, blockId, name, kinds);218}219 220std::string221fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules,222 llvm::ArrayRef<llvm::StringRef> procs,223 std::int64_t blockId, llvm::StringRef name) {224 return prefix()225 .append(doAncestors(modules, procs, blockId))226 .append("E")227 .append(toLower(name));228}229 230std::string231fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,232 llvm::ArrayRef<llvm::StringRef> procs,233 llvm::StringRef name) {234 return prefix()235 .append(doAncestors(modules, procs))236 .append("N")237 .append(toLower(name));238}239 240llvm::StringRef fir::NameUniquer::doProgramEntry() {241 if (mainEntryName.size())242 return mainEntryName;243 return "_QQmain";244}245 246std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName>247fir::NameUniquer::deconstruct(llvm::StringRef uniq) {248 uniq = fir::NameUniquer::dropTypeConversionMarkers(uniq);249 if (uniq.starts_with("_Q")) {250 llvm::SmallVector<std::string> modules;251 llvm::SmallVector<std::string> procs;252 std::int64_t blockId = 0;253 std::string name;254 llvm::SmallVector<std::int64_t> kinds;255 NameKind nk = NameKind::NOT_UNIQUED;256 for (std::size_t i = 2, end{uniq.size()}; i != end;) {257 switch (uniq[i]) {258 case 'B': // Block259 blockId = readInt(uniq, i, i + 1, end);260 break;261 case 'C': // Common block262 nk = NameKind::COMMON;263 name = readName(uniq, i, i + 1, end);264 break;265 case 'D': // Dispatch table266 nk = NameKind::DISPATCH_TABLE;267 assert(uniq[i + 1] == 'T');268 name = readName(uniq, i, i + 2, end);269 break;270 case 'E':271 if (uniq[i + 1] == 'C') { // Constant Entity272 nk = NameKind::CONSTANT;273 name = readName(uniq, i, i + 2, end);274 } else { // variable Entity275 nk = NameKind::VARIABLE;276 name = readName(uniq, i, i + 1, end);277 }278 break;279 case 'F': // procedure/Function ancestor component of a mangled prefix280 procs.push_back(readName(uniq, i, i + 1, end));281 break;282 case 'K':283 if (uniq[i + 1] == 'N') // Negative Kind284 kinds.push_back(-readInt(uniq, i, i + 2, end));285 else // [positive] Kind286 kinds.push_back(readInt(uniq, i, i + 1, end));287 break;288 case 'M': // Module289 case 'S': // Submodule290 modules.push_back(readName(uniq, i, i + 1, end));291 break;292 case 'N': // Namelist group293 nk = NameKind::NAMELIST_GROUP;294 name = readName(uniq, i, i + 1, end);295 break;296 case 'P': // Procedure/function (itself)297 nk = NameKind::PROCEDURE;298 name = readName(uniq, i, i + 1, end);299 break;300 case 'Q': // UniQue mangle name tag301 nk = NameKind::GENERATED;302 name = uniq;303 i = end;304 break;305 case 'T': // derived Type306 nk = NameKind::DERIVED_TYPE;307 name = readName(uniq, i, i + 1, end);308 break;309 case 'Y':310 if (uniq[i + 1] == 'I') { // tYpe descriptor for an Intrinsic type311 nk = NameKind::INTRINSIC_TYPE_DESC;312 name = readName(uniq, i, i + 1, end);313 } else { // tYpe descriptor314 nk = NameKind::TYPE_DESC;315 name = readName(uniq, i, i + 2, end);316 }317 break;318 default:319 assert(false && "unknown uniquing code");320 break;321 }322 }323 return {nk, DeconstructedName(modules, procs, blockId, name, kinds)};324 }325 return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)};326}327 328bool fir::NameUniquer::isExternalFacingUniquedName(329 const std::pair<fir::NameUniquer::NameKind,330 fir::NameUniquer::DeconstructedName> &deconstructResult) {331 return (deconstructResult.first == NameKind::PROCEDURE ||332 deconstructResult.first == NameKind::COMMON) &&333 deconstructResult.second.modules.empty() &&334 deconstructResult.second.procs.empty();335}336 337bool fir::NameUniquer::needExternalNameMangling(llvm::StringRef uniquedName) {338 auto result = fir::NameUniquer::deconstruct(uniquedName);339 return result.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&340 fir::NameUniquer::isExternalFacingUniquedName(result);341}342 343bool fir::NameUniquer::belongsToModule(llvm::StringRef uniquedName,344 llvm::StringRef moduleName) {345 auto result = fir::NameUniquer::deconstruct(uniquedName);346 return !result.second.modules.empty() &&347 result.second.modules[0] == moduleName;348}349 350static std::string351mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) {352 if (kinds.empty())353 return "";354 std::string result;355 for (std::int64_t kind : kinds)356 result += (fir::kNameSeparator + std::to_string(kind)).str();357 return result;358}359 360static std::string getDerivedTypeObjectName(llvm::StringRef mangledTypeName,361 const llvm::StringRef separator) {362 mangledTypeName =363 fir::NameUniquer::dropTypeConversionMarkers(mangledTypeName);364 auto result = fir::NameUniquer::deconstruct(mangledTypeName);365 if (result.first != fir::NameUniquer::NameKind::DERIVED_TYPE)366 return "";367 std::string varName = separator.str() + result.second.name +368 mangleTypeDescriptorKinds(result.second.kinds);369 llvm::SmallVector<llvm::StringRef> modules;370 for (const std::string &mod : result.second.modules)371 modules.push_back(mod);372 llvm::SmallVector<llvm::StringRef> procs;373 for (const std::string &proc : result.second.procs)374 procs.push_back(proc);375 return fir::NameUniquer::doVariable(modules, procs, result.second.blockId,376 varName);377}378 379std::string380fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) {381 return getDerivedTypeObjectName(mangledTypeName,382 fir::kTypeDescriptorSeparator);383}384 385std::string fir::NameUniquer::getTypeDescriptorAssemblyName(386 llvm::StringRef mangledTypeName) {387 return replaceSpecialSymbols(getTypeDescriptorName(mangledTypeName));388}389 390std::string fir::NameUniquer::getTypeDescriptorBindingTableName(391 llvm::StringRef mangledTypeName) {392 return getDerivedTypeObjectName(mangledTypeName, fir::kBindingTableSeparator);393}394 395std::string396fir::NameUniquer::getComponentInitName(llvm::StringRef mangledTypeName,397 llvm::StringRef componentName) {398 399 std::string prefix =400 getDerivedTypeObjectName(mangledTypeName, fir::kComponentInitSeparator);401 return (prefix + fir::kNameSeparator + componentName).str();402}403 404llvm::StringRef405fir::NameUniquer::dropTypeConversionMarkers(llvm::StringRef mangledTypeName) {406 if (mangledTypeName.ends_with(fir::boxprocSuffix))407 return mangledTypeName.drop_back(fir::boxprocSuffix.size());408 return mangledTypeName;409}410 411std::string fir::NameUniquer::replaceSpecialSymbols(const std::string &name) {412 return std::regex_replace(name, std::regex{"\\."}, "X");413}414 415bool fir::NameUniquer::isSpecialSymbol(llvm::StringRef name) {416 return !name.empty() && (name[0] == '.' || name[0] == 'X');417}418