xref: /llvm-project/flang/lib/Optimizer/Support/InternalNames.cpp (revision 86b8c1d9c4a9f540aec2f43989cb8340ae8e9284)
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/
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 
19 static llvm::cl::opt<std::string> mainEntryName(
20     "main-entry-name",
21     llvm::cl::desc("override the name of the default PROGRAM entry (may be "
22                    "helpful for using other runtimes)"));
23 
24 constexpr std::int64_t badValue = -1;
25 
26 inline std::string prefix() { return "_Q"; }
27 
28 static std::string doModules(llvm::ArrayRef<llvm::StringRef> mods) {
29   std::string result;
30   auto *token = "M";
31   for (auto mod : mods) {
32     result.append(token).append(mod.lower());
33     token = "S";
34   }
35   return result;
36 }
37 
38 static std::string doModulesHost(llvm::ArrayRef<llvm::StringRef> mods,
39                                  llvm::Optional<llvm::StringRef> host) {
40   std::string result = doModules(mods);
41   if (host)
42     result.append("F").append(host->lower());
43   return result;
44 }
45 
46 inline llvm::SmallVector<llvm::StringRef>
47 convertToStringRef(llvm::ArrayRef<std::string> from) {
48   return {from.begin(), from.end()};
49 }
50 
51 inline llvm::Optional<llvm::StringRef>
52 convertToStringRef(const llvm::Optional<std::string> &from) {
53   llvm::Optional<llvm::StringRef> to;
54   if (from)
55     to = from.getValue();
56   return to;
57 }
58 
59 static std::string readName(llvm::StringRef uniq, std::size_t &i,
60                             std::size_t init, std::size_t end) {
61   for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z'); ++i) {
62     // do nothing
63   }
64   return uniq.substr(init, i - init).str();
65 }
66 
67 static std::int64_t readInt(llvm::StringRef uniq, std::size_t &i,
68                             std::size_t init, std::size_t end) {
69   for (i = init; i < end && uniq[i] >= '0' && uniq[i] <= '9'; ++i) {
70     // do nothing
71   }
72   std::int64_t result = badValue;
73   if (uniq.substr(init, i - init).getAsInteger(10, result))
74     return badValue;
75   return result;
76 }
77 
78 std::string fir::NameUniquer::toLower(llvm::StringRef name) {
79   return name.lower();
80 }
81 
82 std::string fir::NameUniquer::intAsString(std::int64_t i) {
83   assert(i >= 0);
84   return std::to_string(i);
85 }
86 
87 std::string fir::NameUniquer::doKind(std::int64_t kind) {
88   std::string result = "K";
89   if (kind < 0)
90     return result.append("N").append(intAsString(-kind));
91   return result.append(intAsString(kind));
92 }
93 
94 std::string fir::NameUniquer::doKinds(llvm::ArrayRef<std::int64_t> kinds) {
95   std::string result;
96   for (auto i : kinds)
97     result.append(doKind(i));
98   return result;
99 }
100 
101 std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) {
102   std::string result = prefix();
103   return result.append("B").append(toLower(name));
104 }
105 
106 std::string fir::NameUniquer::doBlockData(llvm::StringRef name) {
107   std::string result = prefix();
108   return result.append("L").append(toLower(name));
109 }
110 
111 std::string
112 fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules,
113                              llvm::Optional<llvm::StringRef> host,
114                              llvm::StringRef name) {
115   std::string result = prefix();
116   result.append(doModulesHost(modules, host)).append("EC");
117   return result.append(toLower(name));
118 }
119 
120 std::string
121 fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
122                                   llvm::Optional<llvm::StringRef> host,
123                                   llvm::StringRef name,
124                                   llvm::ArrayRef<std::int64_t> kinds) {
125   std::string result = prefix();
126   result.append(doModulesHost(modules, host)).append("DT");
127   return result.append(toLower(name)).append(doKinds(kinds));
128 }
129 
130 std::string fir::NameUniquer::doGenerated(llvm::StringRef name) {
131   std::string result = prefix();
132   return result.append("Q").append(name);
133 }
134 
135 std::string fir::NameUniquer::doIntrinsicTypeDescriptor(
136     llvm::ArrayRef<llvm::StringRef> modules,
137     llvm::Optional<llvm::StringRef> host, IntrinsicType type,
138     std::int64_t kind) {
139   const char *name = nullptr;
140   switch (type) {
141   case IntrinsicType::CHARACTER:
142     name = "character";
143     break;
144   case IntrinsicType::COMPLEX:
145     name = "complex";
146     break;
147   case IntrinsicType::INTEGER:
148     name = "integer";
149     break;
150   case IntrinsicType::LOGICAL:
151     name = "logical";
152     break;
153   case IntrinsicType::REAL:
154     name = "real";
155     break;
156   }
157   assert(name && "unknown intrinsic type");
158   std::string result = prefix();
159   result.append(doModulesHost(modules, host)).append("C");
160   return result.append(name).append(doKind(kind));
161 }
162 
163 std::string
164 fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
165                               llvm::Optional<llvm::StringRef> host,
166                               llvm::StringRef name) {
167   std::string result = prefix();
168   result.append(doModulesHost(modules, host)).append("P");
169   return result.append(toLower(name));
170 }
171 
172 std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules,
173                                      llvm::Optional<llvm::StringRef> host,
174                                      llvm::StringRef name,
175                                      llvm::ArrayRef<std::int64_t> kinds) {
176   std::string result = prefix();
177   result.append(doModulesHost(modules, host)).append("T");
178   return result.append(toLower(name)).append(doKinds(kinds));
179 }
180 
181 std::string
182 fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
183                                    llvm::Optional<llvm::StringRef> host,
184                                    llvm::StringRef name,
185                                    llvm::ArrayRef<std::int64_t> kinds) {
186   std::string result = prefix();
187   result.append(doModulesHost(modules, host)).append("CT");
188   return result.append(toLower(name)).append(doKinds(kinds));
189 }
190 
191 std::string fir::NameUniquer::doTypeDescriptor(
192     llvm::ArrayRef<std::string> modules, llvm::Optional<std::string> host,
193     llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds) {
194   auto rmodules = convertToStringRef(modules);
195   auto rhost = convertToStringRef(host);
196   return doTypeDescriptor(rmodules, rhost, name, kinds);
197 }
198 
199 std::string
200 fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules,
201                              llvm::Optional<llvm::StringRef> host,
202                              llvm::StringRef name) {
203   std::string result = prefix();
204   result.append(doModulesHost(modules, host)).append("E");
205   return result.append(toLower(name));
206 }
207 
208 std::string
209 fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
210                                   llvm::Optional<llvm::StringRef> host,
211                                   llvm::StringRef name) {
212   std::string result = prefix();
213   result.append(doModulesHost(modules, host)).append("G");
214   return result.append(toLower(name));
215 }
216 
217 llvm::StringRef fir::NameUniquer::doProgramEntry() {
218   if (mainEntryName.size())
219     return mainEntryName;
220   return "_QQmain";
221 }
222 
223 std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName>
224 fir::NameUniquer::deconstruct(llvm::StringRef uniq) {
225   if (uniq.startswith("_Q")) {
226     llvm::SmallVector<std::string> modules;
227     llvm::Optional<std::string> host;
228     std::string name;
229     llvm::SmallVector<std::int64_t> kinds;
230     NameKind nk = NameKind::NOT_UNIQUED;
231     for (std::size_t i = 2, end{uniq.size()}; i != end;) {
232       switch (uniq[i]) {
233       case 'B':
234         nk = NameKind::COMMON;
235         name = readName(uniq, i, i + 1, end);
236         break;
237       case 'C':
238         if (uniq[i + 1] == 'T') {
239           nk = NameKind::TYPE_DESC;
240           name = readName(uniq, i, i + 2, end);
241         } else {
242           nk = NameKind::INTRINSIC_TYPE_DESC;
243           name = readName(uniq, i, i + 1, end);
244         }
245         break;
246       case 'D':
247         nk = NameKind::DISPATCH_TABLE;
248         assert(uniq[i + 1] == 'T');
249         name = readName(uniq, i, i + 2, end);
250         break;
251       case 'E':
252         if (uniq[i + 1] == 'C') {
253           nk = NameKind::CONSTANT;
254           name = readName(uniq, i, i + 2, end);
255         } else {
256           nk = NameKind::VARIABLE;
257           name = readName(uniq, i, i + 1, end);
258         }
259         break;
260       case 'L':
261         nk = NameKind::BLOCK_DATA_NAME;
262         name = readName(uniq, i, i + 1, end);
263         break;
264       case 'P':
265         nk = NameKind::PROCEDURE;
266         name = readName(uniq, i, i + 1, end);
267         break;
268       case 'Q':
269         nk = NameKind::GENERATED;
270         name = uniq;
271         i = end;
272         break;
273       case 'T':
274         nk = NameKind::DERIVED_TYPE;
275         name = readName(uniq, i, i + 1, end);
276         break;
277 
278       case 'M':
279       case 'S':
280         modules.push_back(readName(uniq, i, i + 1, end));
281         break;
282       case 'F':
283         host = readName(uniq, i, i + 1, end);
284         break;
285       case 'K':
286         if (uniq[i + 1] == 'N')
287           kinds.push_back(-readInt(uniq, i, i + 2, end));
288         else
289           kinds.push_back(readInt(uniq, i, i + 1, end));
290         break;
291       case 'G':
292         nk = NameKind::NAMELIST_GROUP;
293         name = readName(uniq, i, i + 1, end);
294         break;
295 
296       default:
297         assert(false && "unknown uniquing code");
298         break;
299       }
300     }
301     return {nk, DeconstructedName(modules, host, name, kinds)};
302   }
303   return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)};
304 }
305 
306 bool fir::NameUniquer::isExternalFacingUniquedName(
307     const std::pair<fir::NameUniquer::NameKind,
308                     fir::NameUniquer::DeconstructedName> &deconstructResult) {
309   return (deconstructResult.first == NameKind::PROCEDURE ||
310           deconstructResult.first == NameKind::COMMON) &&
311          deconstructResult.second.modules.empty() &&
312          !deconstructResult.second.host;
313 }
314 
315 bool fir::NameUniquer::needExternalNameMangling(llvm::StringRef uniquedName) {
316   auto result = fir::NameUniquer::deconstruct(uniquedName);
317   return result.first != fir::NameUniquer::NameKind::NOT_UNIQUED &&
318          fir::NameUniquer::isExternalFacingUniquedName(result);
319 }
320 
321 bool fir::NameUniquer::belongsToModule(llvm::StringRef uniquedName,
322                                        llvm::StringRef moduleName) {
323   auto result = fir::NameUniquer::deconstruct(uniquedName);
324   return !result.second.modules.empty() &&
325          result.second.modules[0] == moduleName;
326 }
327 
328 static std::string
329 mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) {
330   if (kinds.empty())
331     return "";
332   std::string result = "";
333   for (std::int64_t kind : kinds)
334     result += "." + std::to_string(kind);
335   return result;
336 }
337 
338 std::string
339 fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) {
340   auto result = deconstruct(mangledTypeName);
341   if (result.first != NameKind::DERIVED_TYPE)
342     return "";
343   std::string varName = ".dt." + result.second.name +
344                         mangleTypeDescriptorKinds(result.second.kinds);
345   llvm::SmallVector<llvm::StringRef> modules;
346   for (const std::string &mod : result.second.modules)
347     modules.push_back(mod);
348   llvm::Optional<llvm::StringRef> host;
349   if (result.second.host)
350     host = *result.second.host;
351   return doVariable(modules, host, varName);
352 }
353