1 //===-- InternalNames.cpp -------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
20 static llvm::cl::opt
<std::string
> mainEntryName(
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) {
35 const char *tag
= "M";
36 for (auto mod
: modules
) {
37 prefix
.append(tag
).append(mod
.lower());
40 for (auto proc
: procs
)
41 prefix
.append("F").append(proc
.lower());
43 prefix
.append("B").append(std::to_string(blockId
));
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
;
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
) {
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
) {
73 std::int64_t result
= badValue
;
74 if (uniq
.substr(init
, i
- init
).getAsInteger(10, result
))
79 std::string
fir::NameUniquer::toLower(llvm::StringRef name
) {
83 std::string
fir::NameUniquer::intAsString(std::int64_t i
) {
85 return std::to_string(i
);
88 std::string
fir::NameUniquer::doKind(std::int64_t kind
) {
89 std::string result
= "K";
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
) {
98 result
.append(doKind(i
));
102 std::string
fir::NameUniquer::doCommonBlock(llvm::StringRef name
) {
103 std::string result
= prefix();
104 return result
.append("C").append(toLower(name
));
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
));
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;
137 case IntrinsicType::CHARACTER
:
140 case IntrinsicType::COMPLEX
:
143 case IntrinsicType::INTEGER
:
146 case IntrinsicType::LOGICAL
:
149 case IntrinsicType::REAL
:
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
));
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
));
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
));
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
);
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
));
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
;
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;
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
;) {
233 blockId
= readInt(uniq
, i
, i
+ 1, end
);
235 case 'C': // Common block
236 nk
= NameKind::COMMON
;
237 name
= readName(uniq
, i
, i
+ 1, end
);
239 case 'D': // Dispatch table
240 nk
= NameKind::DISPATCH_TABLE
;
241 assert(uniq
[i
+ 1] == 'T');
242 name
= readName(uniq
, i
, i
+ 2, end
);
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
);
253 case 'F': // procedure/Function ancestor component of a mangled prefix
254 procs
.push_back(readName(uniq
, i
, i
+ 1, end
));
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
));
263 case 'S': // Submodule
264 modules
.push_back(readName(uniq
, i
, i
+ 1, end
));
266 case 'N': // Namelist group
267 nk
= NameKind::NAMELIST_GROUP
;
268 name
= readName(uniq
, i
, i
+ 1, end
);
270 case 'P': // Procedure/function (itself)
271 nk
= NameKind::PROCEDURE
;
272 name
= readName(uniq
, i
, i
+ 1, end
);
274 case 'Q': // UniQue mangle name tag
275 nk
= NameKind::GENERATED
;
279 case 'T': // derived Type
280 nk
= NameKind::DERIVED_TYPE
;
281 name
= readName(uniq
, i
, i
+ 1, end
);
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
);
293 assert(false && "unknown uniquing code");
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
;
325 mangleTypeDescriptorKinds(llvm::ArrayRef
<std::int64_t> kinds
) {
329 for (std::int64_t kind
: kinds
)
330 result
+= "." + std::to_string(kind
);
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
)
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
,
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
);