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