[lldb] Add ability to hide the root name of a value
[llvm-project.git] / flang / lib / Optimizer / Support / InternalNames.cpp
blobdf99cc7243f00c667da250d5df17c18da3793983
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
11 //===----------------------------------------------------------------------===//
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>
20 static llvm::cl::opt<std::string> mainEntryName(
21 "main-entry-name",
22 llvm::cl::desc("override the name of the default PROGRAM entry (may be "
23 "helpful for using other runtimes)"));
25 constexpr std::int64_t badValue = -1;
27 inline std::string prefix() { return "_Q"; }
29 /// Generate a mangling prefix from module, submodule, procedure, and
30 /// statement function names, plus an (innermost) block scope id.
31 static std::string doAncestors(llvm::ArrayRef<llvm::StringRef> modules,
32 llvm::ArrayRef<llvm::StringRef> procs,
33 std::int64_t blockId = 0) {
34 std::string prefix;
35 const char *tag = "M";
36 for (auto mod : modules) {
37 prefix.append(tag).append(mod.lower());
38 tag = "S";
40 for (auto proc : procs)
41 prefix.append("F").append(proc.lower());
42 if (blockId)
43 prefix.append("B").append(std::to_string(blockId));
44 return prefix;
47 inline llvm::SmallVector<llvm::StringRef>
48 convertToStringRef(llvm::ArrayRef<std::string> from) {
49 return {from.begin(), from.end()};
52 inline std::optional<llvm::StringRef>
53 convertToStringRef(const std::optional<std::string> &from) {
54 std::optional<llvm::StringRef> to;
55 if (from)
56 to = *from;
57 return to;
60 static std::string readName(llvm::StringRef uniq, std::size_t &i,
61 std::size_t init, std::size_t end) {
62 for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z'); ++i) {
63 // do nothing
65 return uniq.substr(init, i - init).str();
68 static std::int64_t readInt(llvm::StringRef uniq, std::size_t &i,
69 std::size_t init, std::size_t end) {
70 for (i = init; i < end && uniq[i] >= '0' && uniq[i] <= '9'; ++i) {
71 // do nothing
73 std::int64_t result = badValue;
74 if (uniq.substr(init, i - init).getAsInteger(10, result))
75 return badValue;
76 return result;
79 std::string fir::NameUniquer::toLower(llvm::StringRef name) {
80 return name.lower();
83 std::string fir::NameUniquer::intAsString(std::int64_t i) {
84 assert(i >= 0);
85 return std::to_string(i);
88 std::string fir::NameUniquer::doKind(std::int64_t kind) {
89 std::string result = "K";
90 if (kind < 0)
91 return result.append("N").append(intAsString(-kind));
92 return result.append(intAsString(kind));
95 std::string fir::NameUniquer::doKinds(llvm::ArrayRef<std::int64_t> kinds) {
96 std::string result;
97 for (auto i : kinds)
98 result.append(doKind(i));
99 return result;
102 std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) {
103 std::string result = prefix();
104 return result.append("C").append(toLower(name));
107 std::string
108 fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules,
109 llvm::ArrayRef<llvm::StringRef> procs,
110 std::int64_t blockId, llvm::StringRef name) {
111 std::string result = prefix();
112 result.append(doAncestors(modules, procs, blockId)).append("EC");
113 return result.append(toLower(name));
116 std::string
117 fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
118 llvm::ArrayRef<llvm::StringRef> procs,
119 std::int64_t blockId, llvm::StringRef name,
120 llvm::ArrayRef<std::int64_t> kinds) {
121 std::string result = prefix();
122 result.append(doAncestors(modules, procs, blockId)).append("DT");
123 return result.append(toLower(name)).append(doKinds(kinds));
126 std::string fir::NameUniquer::doGenerated(llvm::StringRef name) {
127 std::string result = prefix();
128 return result.append("Q").append(name);
131 std::string fir::NameUniquer::doIntrinsicTypeDescriptor(
132 llvm::ArrayRef<llvm::StringRef> modules,
133 llvm::ArrayRef<llvm::StringRef> procs, std::int64_t blockId,
134 IntrinsicType type, std::int64_t kind) {
135 const char *name = nullptr;
136 switch (type) {
137 case IntrinsicType::CHARACTER:
138 name = "character";
139 break;
140 case IntrinsicType::COMPLEX:
141 name = "complex";
142 break;
143 case IntrinsicType::INTEGER:
144 name = "integer";
145 break;
146 case IntrinsicType::LOGICAL:
147 name = "logical";
148 break;
149 case IntrinsicType::REAL:
150 name = "real";
151 break;
153 assert(name && "unknown intrinsic type");
154 std::string result = prefix();
155 result.append(doAncestors(modules, procs, blockId)).append("YI");
156 return result.append(name).append(doKind(kind));
159 std::string
160 fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
161 llvm::ArrayRef<llvm::StringRef> procs,
162 llvm::StringRef name) {
163 std::string result = prefix();
164 result.append(doAncestors(modules, procs)).append("P");
165 return result.append(toLower(name));
168 std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules,
169 llvm::ArrayRef<llvm::StringRef> procs,
170 std::int64_t blockId, llvm::StringRef name,
171 llvm::ArrayRef<std::int64_t> kinds) {
172 std::string result = prefix();
173 result.append(doAncestors(modules, procs, blockId)).append("T");
174 return result.append(toLower(name)).append(doKinds(kinds));
177 std::string
178 fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
179 llvm::ArrayRef<llvm::StringRef> procs,
180 std::int64_t blockId, llvm::StringRef name,
181 llvm::ArrayRef<std::int64_t> kinds) {
182 std::string result = prefix();
183 result.append(doAncestors(modules, procs, blockId)).append("CT");
184 return result.append(toLower(name)).append(doKinds(kinds));
187 std::string
188 fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<std::string> modules,
189 llvm::ArrayRef<std::string> procs,
190 std::int64_t blockId, llvm::StringRef name,
191 llvm::ArrayRef<std::int64_t> kinds) {
192 auto rmodules = convertToStringRef(modules);
193 auto rprocs = convertToStringRef(procs);
194 return doTypeDescriptor(rmodules, rprocs, blockId, name, kinds);
197 std::string
198 fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules,
199 llvm::ArrayRef<llvm::StringRef> procs,
200 std::int64_t blockId, llvm::StringRef name) {
201 std::string result = prefix();
202 result.append(doAncestors(modules, procs, blockId)).append("E");
203 return result.append(toLower(name));
206 std::string
207 fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
208 llvm::ArrayRef<llvm::StringRef> procs,
209 llvm::StringRef name) {
210 std::string result = prefix();
211 result.append(doAncestors(modules, procs)).append("N");
212 return result.append(toLower(name));
215 llvm::StringRef fir::NameUniquer::doProgramEntry() {
216 if (mainEntryName.size())
217 return mainEntryName;
218 return "_QQmain";
221 std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName>
222 fir::NameUniquer::deconstruct(llvm::StringRef uniq) {
223 if (uniq.startswith("_Q")) {
224 llvm::SmallVector<std::string> modules;
225 llvm::SmallVector<std::string> procs;
226 std::int64_t blockId = 0;
227 std::string name;
228 llvm::SmallVector<std::int64_t> kinds;
229 NameKind nk = NameKind::NOT_UNIQUED;
230 for (std::size_t i = 2, end{uniq.size()}; i != end;) {
231 switch (uniq[i]) {
232 case 'B': // Block
233 blockId = readInt(uniq, i, i + 1, end);
234 break;
235 case 'C': // Common block
236 nk = NameKind::COMMON;
237 name = readName(uniq, i, i + 1, end);
238 break;
239 case 'D': // Dispatch table
240 nk = NameKind::DISPATCH_TABLE;
241 assert(uniq[i + 1] == 'T');
242 name = readName(uniq, i, i + 2, end);
243 break;
244 case 'E':
245 if (uniq[i + 1] == 'C') { // Constant Entity
246 nk = NameKind::CONSTANT;
247 name = readName(uniq, i, i + 2, end);
248 } else { // variable Entity
249 nk = NameKind::VARIABLE;
250 name = readName(uniq, i, i + 1, end);
252 break;
253 case 'F': // procedure/Function ancestor component of a mangled prefix
254 procs.push_back(readName(uniq, i, i + 1, end));
255 break;
256 case 'K':
257 if (uniq[i + 1] == 'N') // Negative Kind
258 kinds.push_back(-readInt(uniq, i, i + 2, end));
259 else // [positive] Kind
260 kinds.push_back(readInt(uniq, i, i + 1, end));
261 break;
262 case 'M': // Module
263 case 'S': // Submodule
264 modules.push_back(readName(uniq, i, i + 1, end));
265 break;
266 case 'N': // Namelist group
267 nk = NameKind::NAMELIST_GROUP;
268 name = readName(uniq, i, i + 1, end);
269 break;
270 case 'P': // Procedure/function (itself)
271 nk = NameKind::PROCEDURE;
272 name = readName(uniq, i, i + 1, end);
273 break;
274 case 'Q': // UniQue mangle name tag
275 nk = NameKind::GENERATED;
276 name = uniq;
277 i = end;
278 break;
279 case 'T': // derived Type
280 nk = NameKind::DERIVED_TYPE;
281 name = readName(uniq, i, i + 1, end);
282 break;
283 case 'Y':
284 if (uniq[i + 1] == 'I') { // tYpe descriptor for an Intrinsic type
285 nk = NameKind::INTRINSIC_TYPE_DESC;
286 name = readName(uniq, i, i + 1, end);
287 } else { // tYpe descriptor
288 nk = NameKind::TYPE_DESC;
289 name = readName(uniq, i, i + 2, end);
291 break;
292 default:
293 assert(false && "unknown uniquing code");
294 break;
297 return {nk, DeconstructedName(modules, procs, blockId, name, kinds)};
299 return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)};
302 bool fir::NameUniquer::isExternalFacingUniquedName(
303 const std::pair<fir::NameUniquer::NameKind,
304 fir::NameUniquer::DeconstructedName> &deconstructResult) {
305 return (deconstructResult.first == NameKind::PROCEDURE ||
306 deconstructResult.first == NameKind::COMMON) &&
307 deconstructResult.second.modules.empty() &&
308 deconstructResult.second.procs.empty();
311 bool fir::NameUniquer::needExternalNameMangling(llvm::StringRef uniquedName) {
312 auto result = fir::NameUniquer::deconstruct(uniquedName);
313 return result.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&
314 fir::NameUniquer::isExternalFacingUniquedName(result);
317 bool fir::NameUniquer::belongsToModule(llvm::StringRef uniquedName,
318 llvm::StringRef moduleName) {
319 auto result = fir::NameUniquer::deconstruct(uniquedName);
320 return !result.second.modules.empty() &&
321 result.second.modules[0] == moduleName;
324 static std::string
325 mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) {
326 if (kinds.empty())
327 return "";
328 std::string result;
329 for (std::int64_t kind : kinds)
330 result += "." + std::to_string(kind);
331 return result;
334 static std::string getDerivedTypeObjectName(llvm::StringRef mangledTypeName,
335 const llvm::StringRef separator) {
336 if (mangledTypeName.ends_with(boxprocSuffix))
337 mangledTypeName = mangledTypeName.drop_back(boxprocSuffix.size());
338 auto result = fir::NameUniquer::deconstruct(mangledTypeName);
339 if (result.first != fir::NameUniquer::NameKind::DERIVED_TYPE)
340 return "";
341 std::string varName = separator.str() + result.second.name +
342 mangleTypeDescriptorKinds(result.second.kinds);
343 llvm::SmallVector<llvm::StringRef> modules;
344 for (const std::string &mod : result.second.modules)
345 modules.push_back(mod);
346 llvm::SmallVector<llvm::StringRef> procs;
347 for (const std::string &proc : result.second.procs)
348 procs.push_back(proc);
349 return fir::NameUniquer::doVariable(modules, procs, result.second.blockId,
350 varName);
353 std::string
354 fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) {
355 return getDerivedTypeObjectName(mangledTypeName, typeDescriptorSeparator);
358 std::string fir::NameUniquer::getTypeDescriptorBindingTableName(
359 llvm::StringRef mangledTypeName) {
360 return getDerivedTypeObjectName(mangledTypeName, bindingTableSeparator);