xref: /llvm-project/flang/include/flang/Optimizer/Support/InternalNames.h (revision 95b4128c6a87e9b894aa75524e63be147cca790b)
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 FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
10 #define FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/StringRef.h"
14 #include <cstdint>
15 #include <optional>
16 
17 namespace fir {
18 
19 static constexpr llvm::StringRef kNameSeparator = ".";
20 static constexpr llvm::StringRef kBoundsSeparator = ".b.";
21 static constexpr llvm::StringRef kComponentSeparator = ".c.";
22 static constexpr llvm::StringRef kComponentInitSeparator = ".di.";
23 static constexpr llvm::StringRef kDataPtrInitSeparator = ".dp.";
24 static constexpr llvm::StringRef kTypeDescriptorSeparator = ".dt.";
25 static constexpr llvm::StringRef kKindParameterSeparator = ".kp.";
26 static constexpr llvm::StringRef kLenKindSeparator = ".lpk.";
27 static constexpr llvm::StringRef kLenParameterSeparator = ".lv.";
28 static constexpr llvm::StringRef kNameStringSeparator = ".n.";
29 static constexpr llvm::StringRef kProcPtrSeparator = ".p.";
30 static constexpr llvm::StringRef kSpecialBindingSeparator = ".s.";
31 static constexpr llvm::StringRef kBindingTableSeparator = ".v.";
32 static constexpr llvm::StringRef boxprocSuffix = "UnboxProc";
33 
34 /// Internal name mangling of identifiers
35 ///
36 /// In order to generate symbolically referencable artifacts in a ModuleOp,
37 /// it is required that those symbols be uniqued.  This is a simple interface
38 /// for converting Fortran symbols into unique names.
39 ///
40 /// This is intentionally bijective. Given a symbol's parse name, type, and
41 /// scope-like information, we can generate a uniqued (mangled) name.  Given a
42 /// uniqued name, we can return the symbol parse name, type of the symbol, and
43 /// any scope-like information for that symbol.
44 struct NameUniquer {
45   enum class IntrinsicType { CHARACTER, COMPLEX, INTEGER, LOGICAL, REAL };
46 
47   /// The sort of the unique name
48   enum class NameKind {
49     NOT_UNIQUED,
50     BLOCK_DATA_NAME,
51     COMMON,
52     CONSTANT,
53     DERIVED_TYPE,
54     DISPATCH_TABLE,
55     GENERATED,
56     INTRINSIC_TYPE_DESC,
57     NAMELIST_GROUP,
58     PROCEDURE,
59     TYPE_DESC,
60     VARIABLE
61   };
62 
63   /// Components of an unparsed unique name
64   struct DeconstructedName {
65     DeconstructedName(llvm::StringRef name) : name{name} {}
66     DeconstructedName(llvm::ArrayRef<std::string> modules,
67                       llvm::ArrayRef<std::string> procs, std::int64_t blockId,
68                       llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds)
69         : modules{modules}, procs{procs}, blockId{blockId}, name{name},
70           kinds{kinds} {}
71 
72     llvm::SmallVector<std::string> modules;
73     llvm::SmallVector<std::string> procs;
74     std::int64_t blockId;
75     std::string name;
76     llvm::SmallVector<std::int64_t> kinds;
77   };
78 
79   /// Unique a common block name
80   static std::string doCommonBlock(llvm::StringRef name);
81 
82   /// Unique a (global) constant name
83   static std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
84                                 llvm::ArrayRef<llvm::StringRef> procs,
85                                 std::int64_t block, llvm::StringRef name);
86 
87   /// Unique a dispatch table name
88   static std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
89                                      llvm::ArrayRef<llvm::StringRef> procs,
90                                      std::int64_t block, llvm::StringRef name,
91                                      llvm::ArrayRef<std::int64_t> kinds);
92 
93   /// Unique a compiler generated name without scope context.
94   static std::string doGenerated(llvm::StringRef name);
95   /// Unique a compiler generated name with scope context.
96   static std::string doGenerated(llvm::ArrayRef<llvm::StringRef> modules,
97                                  llvm::ArrayRef<llvm::StringRef> procs,
98                                  std::int64_t blockId, llvm::StringRef name);
99 
100   /// Unique an intrinsic type descriptor
101   static std::string
102   doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
103                             llvm::ArrayRef<llvm::StringRef> procs,
104                             std::int64_t block, IntrinsicType type,
105                             std::int64_t kind);
106 
107   /// Unique a procedure name
108   static std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
109                                  llvm::ArrayRef<llvm::StringRef> procs,
110                                  llvm::StringRef name);
111 
112   /// Unique a derived type name
113   static std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
114                             llvm::ArrayRef<llvm::StringRef> procs,
115                             std::int64_t block, llvm::StringRef name,
116                             llvm::ArrayRef<std::int64_t> kinds);
117 
118   /// Unique a (derived) type descriptor name
119   static std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
120                                       llvm::ArrayRef<llvm::StringRef> procs,
121                                       std::int64_t block, llvm::StringRef name,
122                                       llvm::ArrayRef<std::int64_t> kinds);
123   static std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
124                                       llvm::ArrayRef<std::string> procs,
125                                       std::int64_t block, llvm::StringRef name,
126                                       llvm::ArrayRef<std::int64_t> kinds);
127 
128   /// Unique a (global) variable name. A variable with save attribute
129   /// defined inside a subprogram also needs to be handled here
130   static std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
131                                 llvm::ArrayRef<llvm::StringRef> procs,
132                                 std::int64_t block, llvm::StringRef name);
133 
134   /// Unique a namelist group name
135   static std::string doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
136                                      llvm::ArrayRef<llvm::StringRef> procs,
137                                      llvm::StringRef name);
138 
139   /// Entry point for the PROGRAM (called by the runtime)
140   /// Can be overridden with the `--main-entry-name=<name>` option.
141   static llvm::StringRef doProgramEntry();
142 
143   /// Decompose `uniquedName` into the parse name, symbol type, and scope info
144   static std::pair<NameKind, DeconstructedName>
145   deconstruct(llvm::StringRef uniquedName);
146 
147   /// Check if the name is an external facing name.
148   static bool isExternalFacingUniquedName(
149       const std::pair<NameKind, DeconstructedName> &deconstructResult);
150 
151   /// Check whether the name should be re-mangle with external ABI convention.
152   static bool needExternalNameMangling(llvm::StringRef uniquedName);
153 
154   /// Does \p uniquedName belong to module \p moduleName?
155   static bool belongsToModule(llvm::StringRef uniquedName,
156                               llvm::StringRef moduleName);
157 
158   /// Given a mangled derived type name, get the name of the related derived
159   /// type descriptor object. Returns an empty string if \p mangledTypeName is
160   /// not a valid mangled derived type name.
161   static std::string getTypeDescriptorName(llvm::StringRef mangledTypeName);
162 
163   static std::string
164   getTypeDescriptorAssemblyName(llvm::StringRef mangledTypeName);
165 
166   /// Given a mangled derived type name, get the name of the related binding
167   /// table object. Returns an empty string if \p mangledTypeName is not a valid
168   /// mangled derived type name.
169   static std::string
170   getTypeDescriptorBindingTableName(llvm::StringRef mangledTypeName);
171 
172   /// Given a mangled derived type name and a component name, get the name of
173   /// the global object containing the component default initialization.
174   static std::string getComponentInitName(llvm::StringRef mangledTypeName,
175                                           llvm::StringRef componentName);
176 
177   /// Remove markers that have been added when doing partial type
178   /// conversions. mlir::Type cannot be mutated in a pass, so new
179   /// fir::RecordType must be created when lowering member types.
180   /// Suffixes added to these new types are meaningless and are
181   /// dropped in the names passed to LLVM.
182   static llvm::StringRef
183   dropTypeConversionMarkers(llvm::StringRef mangledTypeName);
184 
185   static std::string replaceSpecialSymbols(const std::string &name);
186 
187   /// Returns true if the passed name denotes a special symbol (e.g. global
188   /// symbol generated for derived type description).
189   static bool isSpecialSymbol(llvm::StringRef name);
190 
191 private:
192   static std::string intAsString(std::int64_t i);
193   static std::string doKind(std::int64_t kind);
194   static std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
195   static std::string toLower(llvm::StringRef name);
196 
197   NameUniquer() = delete;
198   NameUniquer(const NameUniquer &) = delete;
199   NameUniquer(NameUniquer &&) = delete;
200   NameUniquer &operator=(const NameUniquer &) = delete;
201 };
202 
203 } // namespace fir
204 
205 #endif // FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
206