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