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 | #include <optional> |
19 | |
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)" )); |
24 | |
25 | constexpr std::int64_t badValue = -1; |
26 | |
27 | inline std::string prefix() { return "_Q" ; } |
28 | |
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(s: tag).append(str: mod.lower()); |
38 | tag = "S" ; |
39 | } |
40 | for (auto proc : procs) |
41 | prefix.append(s: "F" ).append(str: proc.lower()); |
42 | if (blockId) |
43 | prefix.append(s: "B" ).append(str: std::to_string(val: blockId)); |
44 | return prefix; |
45 | } |
46 | |
47 | inline llvm::SmallVector<llvm::StringRef> |
48 | convertToStringRef(llvm::ArrayRef<std::string> from) { |
49 | return {from.begin(), from.end()}; |
50 | } |
51 | |
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; |
58 | } |
59 | |
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 |
64 | } |
65 | return uniq.substr(Start: init, N: i - init).str(); |
66 | } |
67 | |
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 |
72 | } |
73 | std::int64_t result = badValue; |
74 | if (uniq.substr(Start: init, N: i - init).getAsInteger(Radix: 10, Result&: result)) |
75 | return badValue; |
76 | return result; |
77 | } |
78 | |
79 | std::string fir::NameUniquer::toLower(llvm::StringRef name) { |
80 | return name.lower(); |
81 | } |
82 | |
83 | std::string fir::NameUniquer::intAsString(std::int64_t i) { |
84 | assert(i >= 0); |
85 | return std::to_string(i); |
86 | } |
87 | |
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)); |
93 | } |
94 | |
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; |
100 | } |
101 | |
102 | std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) { |
103 | return prefix().append("C" ).append(toLower(name)); |
104 | } |
105 | |
106 | std::string |
107 | fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules, |
108 | llvm::ArrayRef<llvm::StringRef> procs, |
109 | std::int64_t blockId, llvm::StringRef name) { |
110 | return prefix() |
111 | .append(doAncestors(modules, procs, blockId)) |
112 | .append("EC" ) |
113 | .append(toLower(name)); |
114 | } |
115 | |
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 | return prefix() |
122 | .append(doAncestors(modules, procs, blockId)) |
123 | .append("DT" ) |
124 | .append(toLower(name)) |
125 | .append(doKinds(kinds)); |
126 | } |
127 | |
128 | std::string fir::NameUniquer::doGenerated(llvm::StringRef name) { |
129 | return prefix().append("Q" ).append(name); |
130 | } |
131 | |
132 | std::string |
133 | fir::NameUniquer::doGenerated(llvm::ArrayRef<llvm::StringRef> modules, |
134 | llvm::ArrayRef<llvm::StringRef> procs, |
135 | std::int64_t blockId, llvm::StringRef name) { |
136 | return prefix() |
137 | .append("Q" ) |
138 | .append(doAncestors(modules, procs, blockId)) |
139 | .append(name); |
140 | } |
141 | |
142 | std::string fir::NameUniquer::doIntrinsicTypeDescriptor( |
143 | llvm::ArrayRef<llvm::StringRef> modules, |
144 | llvm::ArrayRef<llvm::StringRef> procs, std::int64_t blockId, |
145 | IntrinsicType type, std::int64_t kind) { |
146 | const char *name = nullptr; |
147 | switch (type) { |
148 | case IntrinsicType::CHARACTER: |
149 | name = "character" ; |
150 | break; |
151 | case IntrinsicType::COMPLEX: |
152 | name = "complex" ; |
153 | break; |
154 | case IntrinsicType::INTEGER: |
155 | name = "integer" ; |
156 | break; |
157 | case IntrinsicType::LOGICAL: |
158 | name = "logical" ; |
159 | break; |
160 | case IntrinsicType::REAL: |
161 | name = "real" ; |
162 | break; |
163 | } |
164 | assert(name && "unknown intrinsic type" ); |
165 | return prefix() |
166 | .append(doAncestors(modules, procs, blockId)) |
167 | .append("YI" ) |
168 | .append(name) |
169 | .append(doKind(kind)); |
170 | } |
171 | |
172 | std::string |
173 | fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules, |
174 | llvm::ArrayRef<llvm::StringRef> procs, |
175 | llvm::StringRef name) { |
176 | return prefix() |
177 | .append(doAncestors(modules, procs)) |
178 | .append("P" ) |
179 | .append(toLower(name)); |
180 | } |
181 | |
182 | std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules, |
183 | llvm::ArrayRef<llvm::StringRef> procs, |
184 | std::int64_t blockId, llvm::StringRef name, |
185 | llvm::ArrayRef<std::int64_t> kinds) { |
186 | return prefix() |
187 | .append(doAncestors(modules, procs, blockId)) |
188 | .append("T" ) |
189 | .append(toLower(name)) |
190 | .append(doKinds(kinds)); |
191 | } |
192 | |
193 | std::string |
194 | fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules, |
195 | llvm::ArrayRef<llvm::StringRef> procs, |
196 | std::int64_t blockId, llvm::StringRef name, |
197 | llvm::ArrayRef<std::int64_t> kinds) { |
198 | return prefix() |
199 | .append(doAncestors(modules, procs, blockId)) |
200 | .append("CT" ) |
201 | .append(toLower(name)) |
202 | .append(doKinds(kinds)); |
203 | } |
204 | |
205 | std::string |
206 | fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<std::string> modules, |
207 | llvm::ArrayRef<std::string> procs, |
208 | std::int64_t blockId, llvm::StringRef name, |
209 | llvm::ArrayRef<std::int64_t> kinds) { |
210 | auto rmodules = convertToStringRef(modules); |
211 | auto rprocs = convertToStringRef(procs); |
212 | return doTypeDescriptor(rmodules, rprocs, blockId, name, kinds); |
213 | } |
214 | |
215 | std::string |
216 | fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules, |
217 | llvm::ArrayRef<llvm::StringRef> procs, |
218 | std::int64_t blockId, llvm::StringRef name) { |
219 | return prefix() |
220 | .append(doAncestors(modules, procs, blockId)) |
221 | .append("E" ) |
222 | .append(toLower(name)); |
223 | } |
224 | |
225 | std::string |
226 | fir::NameUniquer::doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules, |
227 | llvm::ArrayRef<llvm::StringRef> procs, |
228 | llvm::StringRef name) { |
229 | return prefix() |
230 | .append(doAncestors(modules, procs)) |
231 | .append("N" ) |
232 | .append(toLower(name)); |
233 | } |
234 | |
235 | llvm::StringRef fir::NameUniquer::doProgramEntry() { |
236 | if (mainEntryName.size()) |
237 | return mainEntryName; |
238 | return "_QQmain" ; |
239 | } |
240 | |
241 | std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName> |
242 | fir::NameUniquer::deconstruct(llvm::StringRef uniq) { |
243 | uniq = fir::NameUniquer::dropTypeConversionMarkers(uniq); |
244 | if (uniq.starts_with("_Q" )) { |
245 | llvm::SmallVector<std::string> modules; |
246 | llvm::SmallVector<std::string> procs; |
247 | std::int64_t blockId = 0; |
248 | std::string name; |
249 | llvm::SmallVector<std::int64_t> kinds; |
250 | NameKind nk = NameKind::NOT_UNIQUED; |
251 | for (std::size_t i = 2, end{uniq.size()}; i != end;) { |
252 | switch (uniq[i]) { |
253 | case 'B': // Block |
254 | blockId = readInt(uniq, i, i + 1, end); |
255 | break; |
256 | case 'C': // Common block |
257 | nk = NameKind::COMMON; |
258 | name = readName(uniq, i, i + 1, end); |
259 | break; |
260 | case 'D': // Dispatch table |
261 | nk = NameKind::DISPATCH_TABLE; |
262 | assert(uniq[i + 1] == 'T'); |
263 | name = readName(uniq, i, i + 2, end); |
264 | break; |
265 | case 'E': |
266 | if (uniq[i + 1] == 'C') { // Constant Entity |
267 | nk = NameKind::CONSTANT; |
268 | name = readName(uniq, i, i + 2, end); |
269 | } else { // variable Entity |
270 | nk = NameKind::VARIABLE; |
271 | name = readName(uniq, i, i + 1, end); |
272 | } |
273 | break; |
274 | case 'F': // procedure/Function ancestor component of a mangled prefix |
275 | procs.push_back(readName(uniq, i, i + 1, end)); |
276 | break; |
277 | case 'K': |
278 | if (uniq[i + 1] == 'N') // Negative Kind |
279 | kinds.push_back(-readInt(uniq, i, i + 2, end)); |
280 | else // [positive] Kind |
281 | kinds.push_back(readInt(uniq, i, i + 1, end)); |
282 | break; |
283 | case 'M': // Module |
284 | case 'S': // Submodule |
285 | modules.push_back(readName(uniq, i, i + 1, end)); |
286 | break; |
287 | case 'N': // Namelist group |
288 | nk = NameKind::NAMELIST_GROUP; |
289 | name = readName(uniq, i, i + 1, end); |
290 | break; |
291 | case 'P': // Procedure/function (itself) |
292 | nk = NameKind::PROCEDURE; |
293 | name = readName(uniq, i, i + 1, end); |
294 | break; |
295 | case 'Q': // UniQue mangle name tag |
296 | nk = NameKind::GENERATED; |
297 | name = uniq; |
298 | i = end; |
299 | break; |
300 | case 'T': // derived Type |
301 | nk = NameKind::DERIVED_TYPE; |
302 | name = readName(uniq, i, i + 1, end); |
303 | break; |
304 | case 'Y': |
305 | if (uniq[i + 1] == 'I') { // tYpe descriptor for an Intrinsic type |
306 | nk = NameKind::INTRINSIC_TYPE_DESC; |
307 | name = readName(uniq, i, i + 1, end); |
308 | } else { // tYpe descriptor |
309 | nk = NameKind::TYPE_DESC; |
310 | name = readName(uniq, i, i + 2, end); |
311 | } |
312 | break; |
313 | default: |
314 | assert(false && "unknown uniquing code" ); |
315 | break; |
316 | } |
317 | } |
318 | return {nk, DeconstructedName(modules, procs, blockId, name, kinds)}; |
319 | } |
320 | return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)}; |
321 | } |
322 | |
323 | bool fir::NameUniquer::isExternalFacingUniquedName( |
324 | const std::pair<fir::NameUniquer::NameKind, |
325 | fir::NameUniquer::DeconstructedName> &deconstructResult) { |
326 | return (deconstructResult.first == NameKind::PROCEDURE || |
327 | deconstructResult.first == NameKind::COMMON) && |
328 | deconstructResult.second.modules.empty() && |
329 | deconstructResult.second.procs.empty(); |
330 | } |
331 | |
332 | bool fir::NameUniquer::needExternalNameMangling(llvm::StringRef uniquedName) { |
333 | auto result = fir::NameUniquer::deconstruct(uniquedName); |
334 | return result.first != fir::NameUniquer::NameKind::NOT_UNIQUED && |
335 | fir::NameUniquer::isExternalFacingUniquedName(result); |
336 | } |
337 | |
338 | bool fir::NameUniquer::belongsToModule(llvm::StringRef uniquedName, |
339 | llvm::StringRef moduleName) { |
340 | auto result = fir::NameUniquer::deconstruct(uniquedName); |
341 | return !result.second.modules.empty() && |
342 | result.second.modules[0] == moduleName; |
343 | } |
344 | |
345 | static std::string |
346 | mangleTypeDescriptorKinds(llvm::ArrayRef<std::int64_t> kinds) { |
347 | if (kinds.empty()) |
348 | return "" ; |
349 | std::string result; |
350 | for (std::int64_t kind : kinds) |
351 | result += "." + std::to_string(val: kind); |
352 | return result; |
353 | } |
354 | |
355 | static std::string getDerivedTypeObjectName(llvm::StringRef mangledTypeName, |
356 | const llvm::StringRef separator) { |
357 | mangledTypeName = |
358 | fir::NameUniquer::dropTypeConversionMarkers(mangledTypeName); |
359 | auto result = fir::NameUniquer::deconstruct(mangledTypeName); |
360 | if (result.first != fir::NameUniquer::NameKind::DERIVED_TYPE) |
361 | return "" ; |
362 | std::string varName = separator.str() + result.second.name + |
363 | mangleTypeDescriptorKinds(result.second.kinds); |
364 | llvm::SmallVector<llvm::StringRef> modules; |
365 | for (const std::string &mod : result.second.modules) |
366 | modules.push_back(mod); |
367 | llvm::SmallVector<llvm::StringRef> procs; |
368 | for (const std::string &proc : result.second.procs) |
369 | procs.push_back(proc); |
370 | return fir::NameUniquer::doVariable(modules, procs, result.second.blockId, |
371 | varName); |
372 | } |
373 | |
374 | std::string |
375 | fir::NameUniquer::getTypeDescriptorName(llvm::StringRef mangledTypeName) { |
376 | return getDerivedTypeObjectName(mangledTypeName, typeDescriptorSeparator); |
377 | } |
378 | |
379 | std::string fir::NameUniquer::getTypeDescriptorBindingTableName( |
380 | llvm::StringRef mangledTypeName) { |
381 | return getDerivedTypeObjectName(mangledTypeName, bindingTableSeparator); |
382 | } |
383 | |
384 | llvm::StringRef |
385 | fir::NameUniquer::dropTypeConversionMarkers(llvm::StringRef mangledTypeName) { |
386 | if (mangledTypeName.ends_with(boxprocSuffix)) |
387 | return mangledTypeName.drop_back(boxprocSuffix.size()); |
388 | return mangledTypeName; |
389 | } |
390 | |