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