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