1 //===-- Optimizer/Support/InternalNames.h -----------------------*- C++ -*-===//
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 #ifndef OPTIMIZER_SUPPORT_INTERNALNAMES_H
10 #define OPTIMIZER_SUPPORT_INTERNALNAMES_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/Optional.h"
14 #include "llvm/ADT/StringRef.h"
15 #include <cstdint>
16 
17 namespace fir {
18 
19 /// Internal name mangling of identifiers
20 ///
21 /// In order to generate symbolically referencable artifacts in a ModuleOp,
22 /// it is required that those symbols be uniqued.  This is a simple interface
23 /// for converting Fortran symbols into unique names.
24 ///
25 /// This is intentionally bijective. Given a symbol's parse name, type, and
26 /// scope-like information, we can generate a uniqued (mangled) name.  Given a
27 /// uniqued name, we can return the symbol parse name, type of the symbol, and
28 /// any scope-like information for that symbol.
29 struct NameUniquer {
30   enum class IntrinsicType { CHARACTER, COMPLEX, INTEGER, LOGICAL, REAL };
31 
32   /// The sort of the unique name
33   enum class NameKind {
34     NOT_UNIQUED,
35     COMMON,
36     CONSTANT,
37     DERIVED_TYPE,
38     DISPATCH_TABLE,
39     GENERATED,
40     INTRINSIC_TYPE_DESC,
41     PROCEDURE,
42     TYPE_DESC,
43     VARIABLE
44   };
45 
46   /// Components of an unparsed unique name
47   struct DeconstructedName {
DeconstructedNameNameUniquer::DeconstructedName48     DeconstructedName(llvm::StringRef name) : name{name} {}
DeconstructedNameNameUniquer::DeconstructedName49     DeconstructedName(llvm::ArrayRef<std::string> modules,
50                       llvm::Optional<std::string> host, llvm::StringRef name,
51                       llvm::ArrayRef<std::int64_t> kinds)
52         : modules{modules.begin(), modules.end()}, host{host}, name{name},
53           kinds{kinds.begin(), kinds.end()} {}
54 
55     llvm::SmallVector<std::string, 2> modules;
56     llvm::Optional<std::string> host;
57     std::string name;
58     llvm::SmallVector<std::int64_t, 4> kinds;
59   };
60 
61   NameUniquer() = default;
62 
63   /// Unique a common block name
64   std::string doCommonBlock(llvm::StringRef name);
65 
66   /// Unique a (global) constant name
67   std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
68                          llvm::Optional<llvm::StringRef> host,
69                          llvm::StringRef name);
70 
71   /// Unique a dispatch table name
72   std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
73                               llvm::Optional<llvm::StringRef> host,
74                               llvm::StringRef name,
75                               llvm::ArrayRef<std::int64_t> kinds);
76 
77   /// Unique a compiler generated name
78   std::string doGenerated(llvm::StringRef name);
79 
80   /// Unique an intrinsic type descriptor
81   std::string doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
82                                         llvm::Optional<llvm::StringRef> host,
83                                         IntrinsicType type, std::int64_t kind);
84 
85   /// Unique a procedure name
86   std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
87                           llvm::Optional<llvm::StringRef> host,
88                           llvm::StringRef name);
89 
90   /// Unique a derived type name
91   std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
92                      llvm::Optional<llvm::StringRef> host, llvm::StringRef name,
93                      llvm::ArrayRef<std::int64_t> kinds);
94 
95   /// Unique a (derived) type descriptor name
96   std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
97                                llvm::Optional<llvm::StringRef> host,
98                                llvm::StringRef name,
99                                llvm::ArrayRef<std::int64_t> kinds);
100   std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
101                                llvm::Optional<std::string> host,
102                                llvm::StringRef name,
103                                llvm::ArrayRef<std::int64_t> kinds);
104 
105   /// Unique a (global) variable name. A variable with save attribute
106   /// defined inside a subprogram also needs to be handled here
107   std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
108                          llvm::Optional<llvm::StringRef> host,
109                          llvm::StringRef name);
110 
111   /// Entry point for the PROGRAM (called by the runtime)
112   /// Can be overridden with the `--main-entry-name=<name>` option.
113   static llvm::StringRef doProgramEntry();
114 
115   /// Decompose `uniquedName` into the parse name, symbol type, and scope info
116   static std::pair<NameKind, DeconstructedName>
117   deconstruct(llvm::StringRef uniquedName);
118 
119 private:
120   std::string intAsString(std::int64_t i);
121   std::string doKind(std::int64_t kind);
122   std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
123   std::string toLower(llvm::StringRef name);
124 };
125 
126 } // namespace fir
127 
128 #endif // OPTIMIZER_SUPPORT_INTERNALNAMES_H
129