1 //===- MipsArchTree.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 // This file contains a helper function for the Writer. 10 // 11 //===---------------------------------------------------------------------===// 12 13 #include "SymbolTable.h" 14 #include "Writer.h" 15 16 #include "lld/Common/ErrorHandler.h" 17 #include "llvm/BinaryFormat/ELF.h" 18 #include "llvm/Support/MipsABIFlags.h" 19 20 using namespace llvm; 21 using namespace llvm::object; 22 using namespace llvm::ELF; 23 24 using namespace lld; 25 using namespace lld::elf; 26 27 namespace { 28 struct ArchTreeEdge { 29 uint32_t child; 30 uint32_t parent; 31 }; 32 33 struct FileFlags { 34 InputFile *file; 35 uint32_t flags; 36 }; 37 } // namespace 38 39 static StringRef getAbiName(uint32_t flags) { 40 switch (flags) { 41 case 0: 42 return "n64"; 43 case EF_MIPS_ABI2: 44 return "n32"; 45 case EF_MIPS_ABI_O32: 46 return "o32"; 47 case EF_MIPS_ABI_O64: 48 return "o64"; 49 case EF_MIPS_ABI_EABI32: 50 return "eabi32"; 51 case EF_MIPS_ABI_EABI64: 52 return "eabi64"; 53 default: 54 return "unknown"; 55 } 56 } 57 58 static StringRef getNanName(bool isNan2008) { 59 return isNan2008 ? "2008" : "legacy"; 60 } 61 62 static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; } 63 64 static void checkFlags(ArrayRef<FileFlags> files) { 65 assert(!files.empty() && "expected non-empty file list"); 66 67 uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2); 68 bool nan = files[0].flags & EF_MIPS_NAN2008; 69 bool fp = files[0].flags & EF_MIPS_FP64; 70 71 for (const FileFlags &f : files) { 72 if (config->is64 && f.flags & EF_MIPS_MICROMIPS) 73 error(toString(f.file) + ": microMIPS 64-bit is not supported"); 74 75 uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2); 76 if (abi != abi2) 77 error(toString(f.file) + ": ABI '" + getAbiName(abi2) + 78 "' is incompatible with target ABI '" + getAbiName(abi) + "'"); 79 80 bool nan2 = f.flags & EF_MIPS_NAN2008; 81 if (nan != nan2) 82 error(toString(f.file) + ": -mnan=" + getNanName(nan2) + 83 " is incompatible with target -mnan=" + getNanName(nan)); 84 85 bool fp2 = f.flags & EF_MIPS_FP64; 86 if (fp != fp2) 87 error(toString(f.file) + ": -mfp" + getFpName(fp2) + 88 " is incompatible with target -mfp" + getFpName(fp)); 89 } 90 } 91 92 static uint32_t getMiscFlags(ArrayRef<FileFlags> files) { 93 uint32_t ret = 0; 94 for (const FileFlags &f : files) 95 ret |= f.flags & 96 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER | 97 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE); 98 return ret; 99 } 100 101 static uint32_t getPicFlags(ArrayRef<FileFlags> files) { 102 // Check PIC/non-PIC compatibility. 103 bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 104 for (const FileFlags &f : files.slice(1)) { 105 bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 106 if (isPic && !isPic2) 107 warn(toString(f.file) + 108 ": linking non-abicalls code with abicalls code " + 109 toString(files[0].file)); 110 if (!isPic && isPic2) 111 warn(toString(f.file) + 112 ": linking abicalls code with non-abicalls code " + 113 toString(files[0].file)); 114 } 115 116 // Compute the result PIC/non-PIC flag. 117 uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 118 for (const FileFlags &f : files.slice(1)) 119 ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 120 121 // PIC code is inherently CPIC and may not set CPIC flag explicitly. 122 if (ret & EF_MIPS_PIC) 123 ret |= EF_MIPS_CPIC; 124 return ret; 125 } 126 127 static ArchTreeEdge archTree[] = { 128 // MIPS32R6 and MIPS64R6 are not compatible with other extensions 129 // MIPS64R2 extensions. 130 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2}, 131 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2}, 132 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2}, 133 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2}, 134 // MIPS64 extensions. 135 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64}, 136 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64}, 137 {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64}, 138 // MIPS V extensions. 139 {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5}, 140 // R5000 extensions. 141 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400}, 142 // MIPS IV extensions. 143 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4}, 144 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4}, 145 {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4}, 146 // VR4100 extensions. 147 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100}, 148 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100}, 149 // MIPS III extensions. 150 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3}, 151 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3}, 152 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3}, 153 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3}, 154 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3}, 155 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3}, 156 {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3}, 157 // MIPS32 extensions. 158 {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32}, 159 // MIPS II extensions. 160 {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2}, 161 {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2}, 162 // MIPS I extensions. 163 {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1}, 164 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1}, 165 }; 166 167 static bool isArchMatched(uint32_t newFlags, uint32_t res) { 168 if (newFlags == res) 169 return true; 170 if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res)) 171 return true; 172 if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res)) 173 return true; 174 for (const auto &edge : archTree) { 175 if (res == edge.child) { 176 res = edge.parent; 177 if (res == newFlags) 178 return true; 179 } 180 } 181 return false; 182 } 183 184 static StringRef getMachName(uint32_t flags) { 185 switch (flags & EF_MIPS_MACH) { 186 case EF_MIPS_MACH_NONE: 187 return ""; 188 case EF_MIPS_MACH_3900: 189 return "r3900"; 190 case EF_MIPS_MACH_4010: 191 return "r4010"; 192 case EF_MIPS_MACH_4100: 193 return "r4100"; 194 case EF_MIPS_MACH_4650: 195 return "r4650"; 196 case EF_MIPS_MACH_4120: 197 return "r4120"; 198 case EF_MIPS_MACH_4111: 199 return "r4111"; 200 case EF_MIPS_MACH_5400: 201 return "vr5400"; 202 case EF_MIPS_MACH_5900: 203 return "vr5900"; 204 case EF_MIPS_MACH_5500: 205 return "vr5500"; 206 case EF_MIPS_MACH_9000: 207 return "rm9000"; 208 case EF_MIPS_MACH_LS2E: 209 return "loongson2e"; 210 case EF_MIPS_MACH_LS2F: 211 return "loongson2f"; 212 case EF_MIPS_MACH_LS3A: 213 return "loongson3a"; 214 case EF_MIPS_MACH_OCTEON: 215 return "octeon"; 216 case EF_MIPS_MACH_OCTEON2: 217 return "octeon2"; 218 case EF_MIPS_MACH_OCTEON3: 219 return "octeon3"; 220 case EF_MIPS_MACH_SB1: 221 return "sb1"; 222 case EF_MIPS_MACH_XLR: 223 return "xlr"; 224 default: 225 return "unknown machine"; 226 } 227 } 228 229 static StringRef getArchName(uint32_t flags) { 230 switch (flags & EF_MIPS_ARCH) { 231 case EF_MIPS_ARCH_1: 232 return "mips1"; 233 case EF_MIPS_ARCH_2: 234 return "mips2"; 235 case EF_MIPS_ARCH_3: 236 return "mips3"; 237 case EF_MIPS_ARCH_4: 238 return "mips4"; 239 case EF_MIPS_ARCH_5: 240 return "mips5"; 241 case EF_MIPS_ARCH_32: 242 return "mips32"; 243 case EF_MIPS_ARCH_64: 244 return "mips64"; 245 case EF_MIPS_ARCH_32R2: 246 return "mips32r2"; 247 case EF_MIPS_ARCH_64R2: 248 return "mips64r2"; 249 case EF_MIPS_ARCH_32R6: 250 return "mips32r6"; 251 case EF_MIPS_ARCH_64R6: 252 return "mips64r6"; 253 default: 254 return "unknown arch"; 255 } 256 } 257 258 static std::string getFullArchName(uint32_t flags) { 259 StringRef arch = getArchName(flags); 260 StringRef mach = getMachName(flags); 261 if (mach.empty()) 262 return arch.str(); 263 return (arch + " (" + mach + ")").str(); 264 } 265 266 // There are (arguably too) many MIPS ISAs out there. Their relationships 267 // can be represented as a forest. If all input files have ISAs which 268 // reachable by repeated proceeding from the single child to the parent, 269 // these input files are compatible. In that case we need to return "highest" 270 // ISA. If there are incompatible input files, we show an error. 271 // For example, mips1 is a "parent" of mips2 and such files are compatible. 272 // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32 273 // are incompatible because nor mips3 is a parent for misp32, nor mips32 274 // is a parent for mips3. 275 static uint32_t getArchFlags(ArrayRef<FileFlags> files) { 276 uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH); 277 278 for (const FileFlags &f : files.slice(1)) { 279 uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH); 280 281 // Check ISA compatibility. 282 if (isArchMatched(newFlags, ret)) 283 continue; 284 if (!isArchMatched(ret, newFlags)) { 285 error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " + 286 getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " + 287 getFullArchName(newFlags)); 288 return 0; 289 } 290 ret = newFlags; 291 } 292 return ret; 293 } 294 295 template <class ELFT> uint32_t elf::calcMipsEFlags() { 296 std::vector<FileFlags> v; 297 for (InputFile *f : objectFiles) 298 v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags}); 299 if (v.empty()) { 300 // If we don't have any input files, we'll have to rely on the information 301 // we can derive from emulation information, since this at least gets us 302 // ABI. 303 if (config->emulation.empty() || config->is64) 304 return 0; 305 return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32; 306 } 307 checkFlags(v); 308 return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v); 309 } 310 311 static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) { 312 if (fpA == fpB) 313 return 0; 314 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY) 315 return 1; 316 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A && 317 fpA == Mips::Val_GNU_MIPS_ABI_FP_64) 318 return 1; 319 if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX) 320 return -1; 321 if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || 322 fpA == Mips::Val_GNU_MIPS_ABI_FP_64 || 323 fpA == Mips::Val_GNU_MIPS_ABI_FP_64A) 324 return 1; 325 return -1; 326 } 327 328 static StringRef getMipsFpAbiName(uint8_t fpAbi) { 329 switch (fpAbi) { 330 case Mips::Val_GNU_MIPS_ABI_FP_ANY: 331 return "any"; 332 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE: 333 return "-mdouble-float"; 334 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE: 335 return "-msingle-float"; 336 case Mips::Val_GNU_MIPS_ABI_FP_SOFT: 337 return "-msoft-float"; 338 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64: 339 return "-mgp32 -mfp64 (old)"; 340 case Mips::Val_GNU_MIPS_ABI_FP_XX: 341 return "-mfpxx"; 342 case Mips::Val_GNU_MIPS_ABI_FP_64: 343 return "-mgp32 -mfp64"; 344 case Mips::Val_GNU_MIPS_ABI_FP_64A: 345 return "-mgp32 -mfp64 -mno-odd-spreg"; 346 default: 347 return "unknown"; 348 } 349 } 350 351 uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag, 352 StringRef fileName) { 353 if (compareMipsFpAbi(newFlag, oldFlag) >= 0) 354 return newFlag; 355 if (compareMipsFpAbi(oldFlag, newFlag) < 0) 356 error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) + 357 "' is incompatible with target floating point ABI '" + 358 getMipsFpAbiName(oldFlag) + "'"); 359 return oldFlag; 360 } 361 362 template <class ELFT> static bool isN32Abi(const InputFile *f) { 363 if (auto *ef = dyn_cast<ELFFileBase>(f)) 364 return ef->template getObj<ELFT>().getHeader().e_flags & EF_MIPS_ABI2; 365 return false; 366 } 367 368 bool elf::isMipsN32Abi(const InputFile *f) { 369 switch (config->ekind) { 370 case ELF32LEKind: 371 return isN32Abi<ELF32LE>(f); 372 case ELF32BEKind: 373 return isN32Abi<ELF32BE>(f); 374 case ELF64LEKind: 375 return isN32Abi<ELF64LE>(f); 376 case ELF64BEKind: 377 return isN32Abi<ELF64BE>(f); 378 default: 379 llvm_unreachable("unknown Config->EKind"); 380 } 381 } 382 383 bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; } 384 385 bool elf::isMipsR6() { 386 uint32_t arch = config->eflags & EF_MIPS_ARCH; 387 return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6; 388 } 389 390 template uint32_t elf::calcMipsEFlags<ELF32LE>(); 391 template uint32_t elf::calcMipsEFlags<ELF32BE>(); 392 template uint32_t elf::calcMipsEFlags<ELF64LE>(); 393 template uint32_t elf::calcMipsEFlags<ELF64BE>(); 394