1f3e3629fSKonstantin Zhuravlyov //===- MipsArchTree.cpp --------------------------------------------------===// 2f3e3629fSKonstantin Zhuravlyov // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f3e3629fSKonstantin Zhuravlyov // 7f3e3629fSKonstantin Zhuravlyov //===---------------------------------------------------------------------===// 8f3e3629fSKonstantin Zhuravlyov // 9f3e3629fSKonstantin Zhuravlyov // This file contains a helper function for the Writer. 10f3e3629fSKonstantin Zhuravlyov // 11f3e3629fSKonstantin Zhuravlyov //===---------------------------------------------------------------------===// 12f3e3629fSKonstantin Zhuravlyov 1338fbedabSFangrui Song #include "InputFiles.h" 14f3e3629fSKonstantin Zhuravlyov #include "SymbolTable.h" 15b3e0bd3dSFangrui Song #include "Target.h" 16f3e3629fSKonstantin Zhuravlyov #include "Writer.h" 17f3e3629fSKonstantin Zhuravlyov 18b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h" 19f3e3629fSKonstantin Zhuravlyov #include "llvm/BinaryFormat/ELF.h" 20f3e3629fSKonstantin Zhuravlyov #include "llvm/Support/MipsABIFlags.h" 21f3e3629fSKonstantin Zhuravlyov 22f3e3629fSKonstantin Zhuravlyov using namespace llvm; 23f3e3629fSKonstantin Zhuravlyov using namespace llvm::object; 24f3e3629fSKonstantin Zhuravlyov using namespace llvm::ELF; 25f3e3629fSKonstantin Zhuravlyov 2607837b8fSFangrui Song using namespace lld; 2707837b8fSFangrui Song using namespace lld::elf; 28f3e3629fSKonstantin Zhuravlyov 29f3e3629fSKonstantin Zhuravlyov namespace { 30f3e3629fSKonstantin Zhuravlyov struct ArchTreeEdge { 313837f427SRui Ueyama uint32_t child; 323837f427SRui Ueyama uint32_t parent; 33f3e3629fSKonstantin Zhuravlyov }; 34f3e3629fSKonstantin Zhuravlyov 35f3e3629fSKonstantin Zhuravlyov struct FileFlags { 363837f427SRui Ueyama InputFile *file; 373837f427SRui Ueyama uint32_t flags; 38f3e3629fSKonstantin Zhuravlyov }; 3967c60727SGeorge Rimar } // namespace 40f3e3629fSKonstantin Zhuravlyov 413837f427SRui Ueyama static StringRef getAbiName(uint32_t flags) { 423837f427SRui Ueyama switch (flags) { 43f3e3629fSKonstantin Zhuravlyov case 0: 44f3e3629fSKonstantin Zhuravlyov return "n64"; 45f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ABI2: 46f3e3629fSKonstantin Zhuravlyov return "n32"; 47f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ABI_O32: 48f3e3629fSKonstantin Zhuravlyov return "o32"; 49f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ABI_O64: 50f3e3629fSKonstantin Zhuravlyov return "o64"; 51f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ABI_EABI32: 52f3e3629fSKonstantin Zhuravlyov return "eabi32"; 53f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ABI_EABI64: 54f3e3629fSKonstantin Zhuravlyov return "eabi64"; 55f3e3629fSKonstantin Zhuravlyov default: 56f3e3629fSKonstantin Zhuravlyov return "unknown"; 57f3e3629fSKonstantin Zhuravlyov } 58f3e3629fSKonstantin Zhuravlyov } 59f3e3629fSKonstantin Zhuravlyov 603837f427SRui Ueyama static StringRef getNanName(bool isNan2008) { 613837f427SRui Ueyama return isNan2008 ? "2008" : "legacy"; 62f3e3629fSKonstantin Zhuravlyov } 63f3e3629fSKonstantin Zhuravlyov 643837f427SRui Ueyama static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; } 65f3e3629fSKonstantin Zhuravlyov 666d03a690SFangrui Song static void checkFlags(Ctx &ctx, ArrayRef<FileFlags> files) { 673837f427SRui Ueyama assert(!files.empty() && "expected non-empty file list"); 6878c46bdfSSimon Atanasyan 693837f427SRui Ueyama uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2); 703837f427SRui Ueyama bool nan = files[0].flags & EF_MIPS_NAN2008; 713837f427SRui Ueyama bool fp = files[0].flags & EF_MIPS_FP64; 72f3e3629fSKonstantin Zhuravlyov 733837f427SRui Ueyama for (const FileFlags &f : files) { 741dd9a565SFangrui Song if (ctx.arg.is64 && f.flags & EF_MIPS_MICROMIPS) 75*c4dc5ed8SFangrui Song Err(ctx) << f.file << ": microMIPS 64-bit is not supported"; 760905b953SSimon Atanasyan 773837f427SRui Ueyama uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2); 783837f427SRui Ueyama if (abi != abi2) 79*c4dc5ed8SFangrui Song Err(ctx) << f.file << ": ABI '" << getAbiName(abi2) 8009c2c5e1SFangrui Song << "' is incompatible with target ABI '" << getAbiName(abi) 8109c2c5e1SFangrui Song << "'"; 82f3e3629fSKonstantin Zhuravlyov 833837f427SRui Ueyama bool nan2 = f.flags & EF_MIPS_NAN2008; 843837f427SRui Ueyama if (nan != nan2) 85*c4dc5ed8SFangrui Song Err(ctx) << f.file << ": -mnan=" << getNanName(nan2) 86*c4dc5ed8SFangrui Song << " is incompatible with target -mnan=" << getNanName(nan); 87f3e3629fSKonstantin Zhuravlyov 883837f427SRui Ueyama bool fp2 = f.flags & EF_MIPS_FP64; 893837f427SRui Ueyama if (fp != fp2) 90*c4dc5ed8SFangrui Song Err(ctx) << f.file << ": -mfp" << getFpName(fp2) 9109c2c5e1SFangrui Song << " is incompatible with target -mfp" << getFpName(fp); 92f3e3629fSKonstantin Zhuravlyov } 93f3e3629fSKonstantin Zhuravlyov } 94f3e3629fSKonstantin Zhuravlyov 953837f427SRui Ueyama static uint32_t getMiscFlags(ArrayRef<FileFlags> files) { 963837f427SRui Ueyama uint32_t ret = 0; 973837f427SRui Ueyama for (const FileFlags &f : files) 983837f427SRui Ueyama ret |= f.flags & 99f3e3629fSKonstantin Zhuravlyov (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER | 100f3e3629fSKonstantin Zhuravlyov EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE); 1013837f427SRui Ueyama return ret; 102f3e3629fSKonstantin Zhuravlyov } 103f3e3629fSKonstantin Zhuravlyov 104e24457a3SFangrui Song static uint32_t getPicFlags(Ctx &ctx, ArrayRef<FileFlags> files) { 105f3e3629fSKonstantin Zhuravlyov // Check PIC/non-PIC compatibility. 1063837f427SRui Ueyama bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 1073837f427SRui Ueyama for (const FileFlags &f : files.slice(1)) { 1083837f427SRui Ueyama bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 1093837f427SRui Ueyama if (isPic && !isPic2) 110f8bae3afSFangrui Song Warn(ctx) << f.file << ": linking non-abicalls code with abicalls code " 111f8bae3afSFangrui Song << files[0].file; 1123837f427SRui Ueyama if (!isPic && isPic2) 113f8bae3afSFangrui Song Warn(ctx) << f.file << ": linking abicalls code with non-abicalls code " 114f8bae3afSFangrui Song << files[0].file; 115f3e3629fSKonstantin Zhuravlyov } 116f3e3629fSKonstantin Zhuravlyov 117f3e3629fSKonstantin Zhuravlyov // Compute the result PIC/non-PIC flag. 1183837f427SRui Ueyama uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 1193837f427SRui Ueyama for (const FileFlags &f : files.slice(1)) 1203837f427SRui Ueyama ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC); 121f3e3629fSKonstantin Zhuravlyov 122f3e3629fSKonstantin Zhuravlyov // PIC code is inherently CPIC and may not set CPIC flag explicitly. 1233837f427SRui Ueyama if (ret & EF_MIPS_PIC) 1243837f427SRui Ueyama ret |= EF_MIPS_CPIC; 1253837f427SRui Ueyama return ret; 126f3e3629fSKonstantin Zhuravlyov } 127f3e3629fSKonstantin Zhuravlyov 1283837f427SRui Ueyama static ArchTreeEdge archTree[] = { 129f3e3629fSKonstantin Zhuravlyov // MIPS32R6 and MIPS64R6 are not compatible with other extensions 130f3e3629fSKonstantin Zhuravlyov // MIPS64R2 extensions. 131f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2}, 132f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2}, 133f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2}, 134f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2}, 135f3e3629fSKonstantin Zhuravlyov // MIPS64 extensions. 136f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64}, 137f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64}, 138f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64}, 139f3e3629fSKonstantin Zhuravlyov // MIPS V extensions. 140f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5}, 141f3e3629fSKonstantin Zhuravlyov // R5000 extensions. 142f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400}, 143f3e3629fSKonstantin Zhuravlyov // MIPS IV extensions. 144f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4}, 145f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4}, 146f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4}, 147f3e3629fSKonstantin Zhuravlyov // VR4100 extensions. 148f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100}, 149f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100}, 150f3e3629fSKonstantin Zhuravlyov // MIPS III extensions. 151f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3}, 152f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3}, 153f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3}, 154f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3}, 155f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3}, 156f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3}, 157f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3}, 158f3e3629fSKonstantin Zhuravlyov // MIPS32 extensions. 159f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32}, 160f3e3629fSKonstantin Zhuravlyov // MIPS II extensions. 161f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2}, 162f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2}, 163f3e3629fSKonstantin Zhuravlyov // MIPS I extensions. 164f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1}, 165f3e3629fSKonstantin Zhuravlyov {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1}, 166f3e3629fSKonstantin Zhuravlyov }; 167f3e3629fSKonstantin Zhuravlyov 168ab04ad6aSFangrui Song static bool isArchMatched(uint32_t newFlags, uint32_t res) { 169ab04ad6aSFangrui Song if (newFlags == res) 170f3e3629fSKonstantin Zhuravlyov return true; 171ab04ad6aSFangrui Song if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res)) 172f3e3629fSKonstantin Zhuravlyov return true; 173ab04ad6aSFangrui Song if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res)) 174f3e3629fSKonstantin Zhuravlyov return true; 1753837f427SRui Ueyama for (const auto &edge : archTree) { 1763837f427SRui Ueyama if (res == edge.child) { 1773837f427SRui Ueyama res = edge.parent; 178ab04ad6aSFangrui Song if (res == newFlags) 179f3e3629fSKonstantin Zhuravlyov return true; 180f3e3629fSKonstantin Zhuravlyov } 181f3e3629fSKonstantin Zhuravlyov } 182f3e3629fSKonstantin Zhuravlyov return false; 183f3e3629fSKonstantin Zhuravlyov } 184f3e3629fSKonstantin Zhuravlyov 1853837f427SRui Ueyama static StringRef getMachName(uint32_t flags) { 1863837f427SRui Ueyama switch (flags & EF_MIPS_MACH) { 187f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_NONE: 188f3e3629fSKonstantin Zhuravlyov return ""; 189f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_3900: 190f3e3629fSKonstantin Zhuravlyov return "r3900"; 191f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_4010: 192f3e3629fSKonstantin Zhuravlyov return "r4010"; 193f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_4100: 194f3e3629fSKonstantin Zhuravlyov return "r4100"; 195f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_4650: 196f3e3629fSKonstantin Zhuravlyov return "r4650"; 197f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_4120: 198f3e3629fSKonstantin Zhuravlyov return "r4120"; 199f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_4111: 200f3e3629fSKonstantin Zhuravlyov return "r4111"; 201f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_5400: 202f3e3629fSKonstantin Zhuravlyov return "vr5400"; 203f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_5900: 204f3e3629fSKonstantin Zhuravlyov return "vr5900"; 205f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_5500: 206f3e3629fSKonstantin Zhuravlyov return "vr5500"; 207f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_9000: 208f3e3629fSKonstantin Zhuravlyov return "rm9000"; 209f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_LS2E: 210f3e3629fSKonstantin Zhuravlyov return "loongson2e"; 211f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_LS2F: 212f3e3629fSKonstantin Zhuravlyov return "loongson2f"; 213f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_LS3A: 214f3e3629fSKonstantin Zhuravlyov return "loongson3a"; 215f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_OCTEON: 216f3e3629fSKonstantin Zhuravlyov return "octeon"; 217f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_OCTEON2: 218f3e3629fSKonstantin Zhuravlyov return "octeon2"; 219f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_OCTEON3: 220f3e3629fSKonstantin Zhuravlyov return "octeon3"; 221f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_SB1: 222f3e3629fSKonstantin Zhuravlyov return "sb1"; 223f3e3629fSKonstantin Zhuravlyov case EF_MIPS_MACH_XLR: 224f3e3629fSKonstantin Zhuravlyov return "xlr"; 225f3e3629fSKonstantin Zhuravlyov default: 226f3e3629fSKonstantin Zhuravlyov return "unknown machine"; 227f3e3629fSKonstantin Zhuravlyov } 228f3e3629fSKonstantin Zhuravlyov } 229f3e3629fSKonstantin Zhuravlyov 2303837f427SRui Ueyama static StringRef getArchName(uint32_t flags) { 2313837f427SRui Ueyama switch (flags & EF_MIPS_ARCH) { 232f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_1: 233f3e3629fSKonstantin Zhuravlyov return "mips1"; 234f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_2: 235f3e3629fSKonstantin Zhuravlyov return "mips2"; 236f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_3: 237f3e3629fSKonstantin Zhuravlyov return "mips3"; 238f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_4: 239f3e3629fSKonstantin Zhuravlyov return "mips4"; 240f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_5: 241f3e3629fSKonstantin Zhuravlyov return "mips5"; 242f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_32: 243f3e3629fSKonstantin Zhuravlyov return "mips32"; 244f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_64: 245f3e3629fSKonstantin Zhuravlyov return "mips64"; 246f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_32R2: 247f3e3629fSKonstantin Zhuravlyov return "mips32r2"; 248f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_64R2: 249f3e3629fSKonstantin Zhuravlyov return "mips64r2"; 250f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_32R6: 251f3e3629fSKonstantin Zhuravlyov return "mips32r6"; 252f3e3629fSKonstantin Zhuravlyov case EF_MIPS_ARCH_64R6: 253f3e3629fSKonstantin Zhuravlyov return "mips64r6"; 254f3e3629fSKonstantin Zhuravlyov default: 255f3e3629fSKonstantin Zhuravlyov return "unknown arch"; 256f3e3629fSKonstantin Zhuravlyov } 257f3e3629fSKonstantin Zhuravlyov } 258f3e3629fSKonstantin Zhuravlyov 2593837f427SRui Ueyama static std::string getFullArchName(uint32_t flags) { 2603837f427SRui Ueyama StringRef arch = getArchName(flags); 2613837f427SRui Ueyama StringRef mach = getMachName(flags); 2623837f427SRui Ueyama if (mach.empty()) 2633837f427SRui Ueyama return arch.str(); 2643837f427SRui Ueyama return (arch + " (" + mach + ")").str(); 265280252c6SAlexander Richardson } 266280252c6SAlexander Richardson 267f3e3629fSKonstantin Zhuravlyov // There are (arguably too) many MIPS ISAs out there. Their relationships 268f3e3629fSKonstantin Zhuravlyov // can be represented as a forest. If all input files have ISAs which 269f3e3629fSKonstantin Zhuravlyov // reachable by repeated proceeding from the single child to the parent, 270f3e3629fSKonstantin Zhuravlyov // these input files are compatible. In that case we need to return "highest" 271f3e3629fSKonstantin Zhuravlyov // ISA. If there are incompatible input files, we show an error. 272f3e3629fSKonstantin Zhuravlyov // For example, mips1 is a "parent" of mips2 and such files are compatible. 273f3e3629fSKonstantin Zhuravlyov // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32 274f3e3629fSKonstantin Zhuravlyov // are incompatible because nor mips3 is a parent for misp32, nor mips32 275f3e3629fSKonstantin Zhuravlyov // is a parent for mips3. 276e24457a3SFangrui Song static uint32_t getArchFlags(Ctx &ctx, ArrayRef<FileFlags> files) { 2773837f427SRui Ueyama uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH); 278f3e3629fSKonstantin Zhuravlyov 2793837f427SRui Ueyama for (const FileFlags &f : files.slice(1)) { 280ab04ad6aSFangrui Song uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH); 281f3e3629fSKonstantin Zhuravlyov 282f3e3629fSKonstantin Zhuravlyov // Check ISA compatibility. 283ab04ad6aSFangrui Song if (isArchMatched(newFlags, ret)) 284f3e3629fSKonstantin Zhuravlyov continue; 285ab04ad6aSFangrui Song if (!isArchMatched(ret, newFlags)) { 286*c4dc5ed8SFangrui Song Err(ctx) << "incompatible target ISA:\n>>> " << files[0].file << ": " 287*c4dc5ed8SFangrui Song << getFullArchName(ret) << "\n>>> " << f.file << ": " 288*c4dc5ed8SFangrui Song << getFullArchName(newFlags); 289f3e3629fSKonstantin Zhuravlyov return 0; 290f3e3629fSKonstantin Zhuravlyov } 291ab04ad6aSFangrui Song ret = newFlags; 292f3e3629fSKonstantin Zhuravlyov } 2933837f427SRui Ueyama return ret; 294f3e3629fSKonstantin Zhuravlyov } 295f3e3629fSKonstantin Zhuravlyov 2966d03a690SFangrui Song template <class ELFT> uint32_t elf::calcMipsEFlags(Ctx &ctx) { 2973837f427SRui Ueyama std::vector<FileFlags> v; 29834fa8600SFangrui Song for (InputFile *f : ctx.objectFiles) 2994845531fSGeorgii Rymar v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags}); 300355764e3SGeorge Rimar if (v.empty()) { 301355764e3SGeorge Rimar // If we don't have any input files, we'll have to rely on the information 302355764e3SGeorge Rimar // we can derive from emulation information, since this at least gets us 303355764e3SGeorge Rimar // ABI. 3041dd9a565SFangrui Song if (ctx.arg.emulation.empty() || ctx.arg.is64) 305355764e3SGeorge Rimar return 0; 3061dd9a565SFangrui Song return ctx.arg.mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32; 307355764e3SGeorge Rimar } 3086d03a690SFangrui Song checkFlags(ctx, v); 309e24457a3SFangrui Song return getMiscFlags(v) | getPicFlags(ctx, v) | getArchFlags(ctx, v); 310f3e3629fSKonstantin Zhuravlyov } 311f3e3629fSKonstantin Zhuravlyov 3123837f427SRui Ueyama static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) { 3133837f427SRui Ueyama if (fpA == fpB) 314f3e3629fSKonstantin Zhuravlyov return 0; 3153837f427SRui Ueyama if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY) 316f3e3629fSKonstantin Zhuravlyov return 1; 3173837f427SRui Ueyama if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A && 3183837f427SRui Ueyama fpA == Mips::Val_GNU_MIPS_ABI_FP_64) 319f3e3629fSKonstantin Zhuravlyov return 1; 3203837f427SRui Ueyama if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX) 321f3e3629fSKonstantin Zhuravlyov return -1; 3223837f427SRui Ueyama if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || 3233837f427SRui Ueyama fpA == Mips::Val_GNU_MIPS_ABI_FP_64 || 3243837f427SRui Ueyama fpA == Mips::Val_GNU_MIPS_ABI_FP_64A) 325f3e3629fSKonstantin Zhuravlyov return 1; 326f3e3629fSKonstantin Zhuravlyov return -1; 327f3e3629fSKonstantin Zhuravlyov } 328f3e3629fSKonstantin Zhuravlyov 3293837f427SRui Ueyama static StringRef getMipsFpAbiName(uint8_t fpAbi) { 3303837f427SRui Ueyama switch (fpAbi) { 331f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_ANY: 332f3e3629fSKonstantin Zhuravlyov return "any"; 333f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE: 334f3e3629fSKonstantin Zhuravlyov return "-mdouble-float"; 335f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_SINGLE: 336f3e3629fSKonstantin Zhuravlyov return "-msingle-float"; 337f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_SOFT: 338f3e3629fSKonstantin Zhuravlyov return "-msoft-float"; 339f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_OLD_64: 34064fb2901SSimon Atanasyan return "-mgp32 -mfp64 (old)"; 341f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_XX: 342f3e3629fSKonstantin Zhuravlyov return "-mfpxx"; 343f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_64: 344f3e3629fSKonstantin Zhuravlyov return "-mgp32 -mfp64"; 345f3e3629fSKonstantin Zhuravlyov case Mips::Val_GNU_MIPS_ABI_FP_64A: 346f3e3629fSKonstantin Zhuravlyov return "-mgp32 -mfp64 -mno-odd-spreg"; 347f3e3629fSKonstantin Zhuravlyov default: 348f3e3629fSKonstantin Zhuravlyov return "unknown"; 349f3e3629fSKonstantin Zhuravlyov } 350f3e3629fSKonstantin Zhuravlyov } 351f3e3629fSKonstantin Zhuravlyov 352*c4dc5ed8SFangrui Song uint8_t elf::getMipsFpAbiFlag(Ctx &ctx, InputFile *file, uint8_t oldFlag, 353*c4dc5ed8SFangrui Song uint8_t newFlag) { 3543837f427SRui Ueyama if (compareMipsFpAbi(newFlag, oldFlag) >= 0) 3553837f427SRui Ueyama return newFlag; 3563837f427SRui Ueyama if (compareMipsFpAbi(oldFlag, newFlag) < 0) 357*c4dc5ed8SFangrui Song Err(ctx) << file << ": floating point ABI '" << getMipsFpAbiName(newFlag) 35809c2c5e1SFangrui Song << "' is incompatible with target floating point ABI '" 35909c2c5e1SFangrui Song << getMipsFpAbiName(oldFlag) << "'"; 3603837f427SRui Ueyama return oldFlag; 361f3e3629fSKonstantin Zhuravlyov } 362f3e3629fSKonstantin Zhuravlyov 3636d03a690SFangrui Song template <class ELFT> static bool isN32Abi(const InputFile &f) { 3646d03a690SFangrui Song if (auto *ef = dyn_cast<ELFFileBase>(&f)) 3654845531fSGeorgii Rymar return ef->template getObj<ELFT>().getHeader().e_flags & EF_MIPS_ABI2; 366f3e3629fSKonstantin Zhuravlyov return false; 367f3e3629fSKonstantin Zhuravlyov } 368f3e3629fSKonstantin Zhuravlyov 3696d03a690SFangrui Song bool elf::isMipsN32Abi(Ctx &ctx, const InputFile &f) { 3701dd9a565SFangrui Song switch (ctx.arg.ekind) { 371f3e3629fSKonstantin Zhuravlyov case ELF32LEKind: 3723837f427SRui Ueyama return isN32Abi<ELF32LE>(f); 373f3e3629fSKonstantin Zhuravlyov case ELF32BEKind: 3743837f427SRui Ueyama return isN32Abi<ELF32BE>(f); 375f3e3629fSKonstantin Zhuravlyov case ELF64LEKind: 3763837f427SRui Ueyama return isN32Abi<ELF64LE>(f); 377f3e3629fSKonstantin Zhuravlyov case ELF64BEKind: 3783837f427SRui Ueyama return isN32Abi<ELF64BE>(f); 379f3e3629fSKonstantin Zhuravlyov default: 380b8248dacSFangrui Song llvm_unreachable("unknown ctx.arg.ekind"); 381f3e3629fSKonstantin Zhuravlyov } 382f3e3629fSKonstantin Zhuravlyov } 383f3e3629fSKonstantin Zhuravlyov 384b3e0bd3dSFangrui Song bool elf::isMicroMips(Ctx &ctx) { return ctx.arg.eflags & EF_MIPS_MICROMIPS; } 385cfa8aa7eSSimon Atanasyan 3866d03a690SFangrui Song bool elf::isMipsR6(Ctx &ctx) { 3871dd9a565SFangrui Song uint32_t arch = ctx.arg.eflags & EF_MIPS_ARCH; 3883837f427SRui Ueyama return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6; 389f8db4536SSimon Atanasyan } 390f8db4536SSimon Atanasyan 3916d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF32LE>(Ctx &); 3926d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF32BE>(Ctx &); 3936d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF64LE>(Ctx &); 3946d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF64BE>(Ctx &); 395