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