1 //===-- InternalNames.cpp -------------------------------------------------===// 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 #include "flang/Optimizer/Support/InternalNames.h" 10 #include "mlir/IR/Diagnostics.h" 11 #include "llvm/Support/CommandLine.h" 12 13 static llvm::cl::opt<std::string> mainEntryName( 14 "main-entry-name", 15 llvm::cl::desc("override the name of the default PROGRAM entry (may be " 16 "helpful for using other runtimes)")); 17 18 constexpr std::int64_t BAD_VALUE = -1; 19 20 inline std::string prefix() { return "_Q"; } 21 22 static std::string doModules(llvm::ArrayRef<llvm::StringRef> mods) { 23 std::string result; 24 auto *token = "M"; 25 for (auto mod : mods) { 26 result.append(token).append(mod.lower()); 27 token = "S"; 28 } 29 return result; 30 } 31 32 static std::string doModulesHost(llvm::ArrayRef<llvm::StringRef> mods, 33 llvm::Optional<llvm::StringRef> host) { 34 std::string result = doModules(mods); 35 if (host.hasValue()) 36 result.append("F").append(host->lower()); 37 return result; 38 } 39 40 inline llvm::SmallVector<llvm::StringRef, 2> 41 convertToStringRef(llvm::ArrayRef<std::string> from) { 42 return {from.begin(), from.end()}; 43 } 44 45 inline llvm::Optional<llvm::StringRef> 46 convertToStringRef(const llvm::Optional<std::string> &from) { 47 llvm::Optional<llvm::StringRef> to; 48 if (from.hasValue()) 49 to = from.getValue(); 50 return to; 51 } 52 53 static std::string readName(llvm::StringRef uniq, std::size_t &i, 54 std::size_t init, std::size_t end) { 55 for (i = init; i < end && (uniq[i] < 'A' || uniq[i] > 'Z'); ++i) { 56 // do nothing 57 } 58 return uniq.substr(init, i - init).str(); 59 } 60 61 static std::int64_t readInt(llvm::StringRef uniq, std::size_t &i, 62 std::size_t init, std::size_t end) { 63 for (i = init; i < end && uniq[i] >= '0' && uniq[i] <= '9'; ++i) { 64 // do nothing 65 } 66 std::int64_t result = BAD_VALUE; 67 if (uniq.substr(init, i - init).getAsInteger(10, result)) 68 return BAD_VALUE; 69 return result; 70 } 71 72 std::string fir::NameUniquer::toLower(llvm::StringRef name) { 73 return name.lower(); 74 } 75 76 std::string fir::NameUniquer::intAsString(std::int64_t i) { 77 assert(i >= 0); 78 return std::to_string(i); 79 } 80 81 std::string fir::NameUniquer::doKind(std::int64_t kind) { 82 std::string result = "K"; 83 if (kind < 0) 84 return result.append("N").append(intAsString(-kind)); 85 return result.append(intAsString(kind)); 86 } 87 88 std::string fir::NameUniquer::doKinds(llvm::ArrayRef<std::int64_t> kinds) { 89 std::string result; 90 for (auto i : kinds) 91 result.append(doKind(i)); 92 return result; 93 } 94 95 std::string fir::NameUniquer::doCommonBlock(llvm::StringRef name) { 96 std::string result = prefix(); 97 return result.append("B").append(toLower(name)); 98 } 99 100 std::string 101 fir::NameUniquer::doConstant(llvm::ArrayRef<llvm::StringRef> modules, 102 llvm::Optional<llvm::StringRef> host, 103 llvm::StringRef name) { 104 std::string result = prefix(); 105 result.append(doModulesHost(modules, host)).append("EC"); 106 return result.append(toLower(name)); 107 } 108 109 std::string 110 fir::NameUniquer::doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules, 111 llvm::Optional<llvm::StringRef> host, 112 llvm::StringRef name, 113 llvm::ArrayRef<std::int64_t> kinds) { 114 std::string result = prefix(); 115 result.append(doModulesHost(modules, host)).append("DT"); 116 return result.append(toLower(name)).append(doKinds(kinds)); 117 } 118 119 std::string fir::NameUniquer::doGenerated(llvm::StringRef name) { 120 std::string result = prefix(); 121 return result.append("Q").append(name); 122 } 123 124 std::string fir::NameUniquer::doIntrinsicTypeDescriptor( 125 llvm::ArrayRef<llvm::StringRef> modules, 126 llvm::Optional<llvm::StringRef> host, IntrinsicType type, 127 std::int64_t kind) { 128 const char *name = nullptr; 129 switch (type) { 130 case IntrinsicType::CHARACTER: 131 name = "character"; 132 break; 133 case IntrinsicType::COMPLEX: 134 name = "complex"; 135 break; 136 case IntrinsicType::INTEGER: 137 name = "integer"; 138 break; 139 case IntrinsicType::LOGICAL: 140 name = "logical"; 141 break; 142 case IntrinsicType::REAL: 143 name = "real"; 144 break; 145 } 146 assert(name && "unknown intrinsic type"); 147 std::string result = prefix(); 148 result.append(doModulesHost(modules, host)).append("C"); 149 return result.append(name).append(doKind(kind)); 150 } 151 152 std::string 153 fir::NameUniquer::doProcedure(llvm::ArrayRef<llvm::StringRef> modules, 154 llvm::Optional<llvm::StringRef> host, 155 llvm::StringRef name) { 156 std::string result = prefix(); 157 result.append(doModulesHost(modules, host)).append("P"); 158 return result.append(toLower(name)); 159 } 160 161 std::string fir::NameUniquer::doType(llvm::ArrayRef<llvm::StringRef> modules, 162 llvm::Optional<llvm::StringRef> host, 163 llvm::StringRef name, 164 llvm::ArrayRef<std::int64_t> kinds) { 165 std::string result = prefix(); 166 result.append(doModulesHost(modules, host)).append("T"); 167 return result.append(toLower(name)).append(doKinds(kinds)); 168 } 169 170 std::string 171 fir::NameUniquer::doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules, 172 llvm::Optional<llvm::StringRef> host, 173 llvm::StringRef name, 174 llvm::ArrayRef<std::int64_t> kinds) { 175 std::string result = prefix(); 176 result.append(doModulesHost(modules, host)).append("CT"); 177 return result.append(toLower(name)).append(doKinds(kinds)); 178 } 179 180 std::string fir::NameUniquer::doTypeDescriptor( 181 llvm::ArrayRef<std::string> modules, llvm::Optional<std::string> host, 182 llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds) { 183 auto rmodules = convertToStringRef(modules); 184 auto rhost = convertToStringRef(host); 185 return doTypeDescriptor(rmodules, rhost, name, kinds); 186 } 187 188 std::string 189 fir::NameUniquer::doVariable(llvm::ArrayRef<llvm::StringRef> modules, 190 llvm::Optional<llvm::StringRef> host, 191 llvm::StringRef name) { 192 std::string result = prefix(); 193 result.append(doModulesHost(modules, host)).append("E"); 194 return result.append(toLower(name)); 195 } 196 197 llvm::StringRef fir::NameUniquer::doProgramEntry() { 198 if (mainEntryName.size()) 199 return mainEntryName; 200 return "_QQmain"; 201 } 202 203 std::pair<fir::NameUniquer::NameKind, fir::NameUniquer::DeconstructedName> 204 fir::NameUniquer::deconstruct(llvm::StringRef uniq) { 205 if (uniq.startswith("_Q")) { 206 llvm::SmallVector<std::string, 4> modules; 207 llvm::Optional<std::string> host; 208 std::string name; 209 llvm::SmallVector<std::int64_t, 8> kinds; 210 NameKind nk = NameKind::NOT_UNIQUED; 211 for (std::size_t i = 2, end{uniq.size()}; i != end;) { 212 switch (uniq[i]) { 213 case 'B': 214 nk = NameKind::COMMON; 215 name = readName(uniq, i, i + 1, end); 216 break; 217 case 'C': 218 if (uniq[i + 1] == 'T') { 219 nk = NameKind::TYPE_DESC; 220 name = readName(uniq, i, i + 2, end); 221 } else { 222 nk = NameKind::INTRINSIC_TYPE_DESC; 223 name = readName(uniq, i, i + 1, end); 224 } 225 break; 226 case 'D': 227 nk = NameKind::DISPATCH_TABLE; 228 assert(uniq[i + 1] == 'T'); 229 name = readName(uniq, i, i + 2, end); 230 break; 231 case 'E': 232 if (uniq[i + 1] == 'C') { 233 nk = NameKind::CONSTANT; 234 name = readName(uniq, i, i + 2, end); 235 } else { 236 nk = NameKind::VARIABLE; 237 name = readName(uniq, i, i + 1, end); 238 } 239 break; 240 case 'P': 241 nk = NameKind::PROCEDURE; 242 name = readName(uniq, i, i + 1, end); 243 break; 244 case 'Q': 245 nk = NameKind::GENERATED; 246 name = uniq; 247 i = end; 248 break; 249 case 'T': 250 nk = NameKind::DERIVED_TYPE; 251 name = readName(uniq, i, i + 1, end); 252 break; 253 254 case 'M': 255 case 'S': 256 modules.push_back(readName(uniq, i, i + 1, end)); 257 break; 258 case 'F': 259 host = readName(uniq, i, i + 1, end); 260 break; 261 case 'K': 262 if (uniq[i + 1] == 'N') 263 kinds.push_back(-readInt(uniq, i, i + 2, end)); 264 else 265 kinds.push_back(readInt(uniq, i, i + 1, end)); 266 break; 267 268 default: 269 assert(false && "unknown uniquing code"); 270 break; 271 } 272 } 273 return {nk, DeconstructedName(modules, host, name, kinds)}; 274 } 275 return {NameKind::NOT_UNIQUED, DeconstructedName(uniq)}; 276 } 277