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
prefix()26 inline std::string prefix() { return "_Q"; }
27
doModules(llvm::ArrayRef<llvm::StringRef> mods)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
doModulesHost(llvm::ArrayRef<llvm::StringRef> mods,llvm::Optional<llvm::StringRef> host)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>
convertToStringRef(llvm::ArrayRef<std::string> from)47 convertToStringRef(llvm::ArrayRef<std::string> from) {
48 return {from.begin(), from.end()};
49 }
50
51 inline llvm::Optional<llvm::StringRef>
convertToStringRef(const llvm::Optional<std::string> & from)52 convertToStringRef(const llvm::Optional<std::string> &from) {
53 llvm::Optional<llvm::StringRef> to;
54 if (from)
55 to = *from;
56 return to;
57 }
58
readName(llvm::StringRef uniq,std::size_t & i,std::size_t init,std::size_t end)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
readInt(llvm::StringRef uniq,std::size_t & i,std::size_t init,std::size_t end)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
toLower(llvm::StringRef name)78 std::string fir::NameUniquer::toLower(llvm::StringRef name) {
79 return name.lower();
80 }
81
intAsString(std::int64_t i)82 std::string fir::NameUniquer::intAsString(std::int64_t i) {
83 assert(i >= 0);
84 return std::to_string(i);
85 }
86
doKind(std::int64_t kind)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
doKinds(llvm::ArrayRef<std::int64_t> kinds)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
doCommonBlock(llvm::StringRef name)101 std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) {
102 std::string result = prefix();
103 return result.append("B").append(toLower(name));
104 }
105
doBlockData(llvm::StringRef name)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
doConstant(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name)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
doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name,llvm::ArrayRef<std::int64_t> kinds)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
doGenerated(llvm::StringRef name)130 std::string fir::NameUniquer::doGenerated(llvm::StringRef name) {
131 std::string result = prefix();
132 return result.append("Q").append(name);
133 }
134
doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,IntrinsicType type,std::int64_t kind)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
doProcedure(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name)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
doType(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name,llvm::ArrayRef<std::int64_t> kinds)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
doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name,llvm::ArrayRef<std::int64_t> kinds)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
doTypeDescriptor(llvm::ArrayRef<std::string> modules,llvm::Optional<std::string> host,llvm::StringRef name,llvm::ArrayRef<std::int64_t> kinds)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
doVariable(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name)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
doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,llvm::Optional<llvm::StringRef> host,llvm::StringRef name)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
doProgramEntry()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>
deconstruct(llvm::StringRef uniq)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
isExternalFacingUniquedName(const std::pair<fir::NameUniquer::NameKind,fir::NameUniquer::DeconstructedName> & deconstructResult)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
needExternalNameMangling(llvm::StringRef uniquedName)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
belongsToModule(llvm::StringRef uniquedName,llvm::StringRef moduleName)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
mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds)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
getTypeDescriptorName(llvm::StringRef mangledTypeName)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