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