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/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     BLOCK_DATA_NAME,
36     COMMON,
37     CONSTANT,
38     DERIVED_TYPE,
39     DISPATCH_TABLE,
40     GENERATED,
41     INTRINSIC_TYPE_DESC,
42     PROCEDURE,
43     TYPE_DESC,
44     VARIABLE,
45     NAMELIST_GROUP
46   };
47 
48   /// Components of an unparsed unique name
49   struct DeconstructedName {
DeconstructedNameNameUniquer::DeconstructedName50     DeconstructedName(llvm::StringRef name) : name{name} {}
DeconstructedNameNameUniquer::DeconstructedName51     DeconstructedName(llvm::ArrayRef<std::string> modules,
52                       llvm::Optional<std::string> host, llvm::StringRef name,
53                       llvm::ArrayRef<std::int64_t> kinds)
54         : modules{modules.begin(), modules.end()}, host{host}, name{name},
55           kinds{kinds.begin(), kinds.end()} {}
56 
57     llvm::SmallVector<std::string> modules;
58     llvm::Optional<std::string> host;
59     std::string name;
60     llvm::SmallVector<std::int64_t> kinds;
61   };
62 
63   /// Unique a common block name
64   static std::string doCommonBlock(llvm::StringRef name);
65 
66   /// Unique a block data unit name
67   static std::string doBlockData(llvm::StringRef name);
68 
69   /// Unique a (global) constant name
70   static std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
71                                 llvm::Optional<llvm::StringRef> host,
72                                 llvm::StringRef name);
73 
74   /// Unique a dispatch table name
75   static std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
76                                      llvm::Optional<llvm::StringRef> host,
77                                      llvm::StringRef name,
78                                      llvm::ArrayRef<std::int64_t> kinds);
79 
80   /// Unique a compiler generated name
81   static std::string doGenerated(llvm::StringRef name);
82 
83   /// Unique an intrinsic type descriptor
84   static std::string
85   doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
86                             llvm::Optional<llvm::StringRef> host,
87                             IntrinsicType type, std::int64_t kind);
88 
89   /// Unique a procedure name
90   static std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
91                                  llvm::Optional<llvm::StringRef> host,
92                                  llvm::StringRef name);
93 
94   /// Unique a derived type name
95   static std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
96                             llvm::Optional<llvm::StringRef> host,
97                             llvm::StringRef name,
98                             llvm::ArrayRef<std::int64_t> kinds);
99 
100   /// Unique a (derived) type descriptor name
101   static std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
102                                       llvm::Optional<llvm::StringRef> host,
103                                       llvm::StringRef name,
104                                       llvm::ArrayRef<std::int64_t> kinds);
105   static std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
106                                       llvm::Optional<std::string> host,
107                                       llvm::StringRef name,
108                                       llvm::ArrayRef<std::int64_t> kinds);
109 
110   /// Unique a (global) variable name. A variable with save attribute
111   /// defined inside a subprogram also needs to be handled here
112   static std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
113                                 llvm::Optional<llvm::StringRef> host,
114                                 llvm::StringRef name);
115 
116   /// Unique a namelist group name
117   static std::string doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
118                                      llvm::Optional<llvm::StringRef> host,
119                                      llvm::StringRef name);
120 
121   /// Entry point for the PROGRAM (called by the runtime)
122   /// Can be overridden with the `--main-entry-name=<name>` option.
123   static llvm::StringRef doProgramEntry();
124 
125   /// Decompose `uniquedName` into the parse name, symbol type, and scope info
126   static std::pair<NameKind, DeconstructedName>
127   deconstruct(llvm::StringRef uniquedName);
128 
129   /// Check if the name is an external facing name.
130   static bool isExternalFacingUniquedName(
131       const std::pair<NameKind, DeconstructedName> &deconstructResult);
132 
133   /// Check whether the name should be re-mangle with external ABI convention.
134   static bool needExternalNameMangling(llvm::StringRef uniquedName);
135 
136   /// Does \p uniquedName belong to module \p moduleName?
137   static bool belongsToModule(llvm::StringRef uniquedName,
138                               llvm::StringRef moduleName);
139 
140   /// Given a mangled derived type name, get the name of the related derived
141   /// type descriptor object. Returns an empty string if \p mangledTypeName is
142   /// not a valid mangled derived type name.
143   static std::string getTypeDescriptorName(llvm::StringRef mangledTypeName);
144 
145 private:
146   static std::string intAsString(std::int64_t i);
147   static std::string doKind(std::int64_t kind);
148   static std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
149   static std::string toLower(llvm::StringRef name);
150 
151   NameUniquer() = delete;
152   NameUniquer(const NameUniquer &) = delete;
153   NameUniquer(NameUniquer &&) = delete;
154   NameUniquer &operator=(const NameUniquer &) = delete;
155 };
156 
157 } // namespace fir
158 
159 #endif // FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
160