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 23 using namespace llvm; 24 using namespace llvm::object; 25 using namespace llvm::ELF; 26 27 using namespace lld; 28 using namespace lld::elf; 29 30 namespace { 31 struct ArchTreeEdge { 32 uint32_t Child; 33 uint32_t Parent; 34 }; 35 36 struct FileFlags { 37 StringRef Filename; 38 uint32_t Flags; 39 }; 40 } // namespace 41 42 static 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 61 static StringRef getNanName(bool IsNan2008) { 62 return IsNan2008 ? "2008" : "legacy"; 63 } 64 65 static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; } 66 67 static 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 90 static 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 99 static 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 121 static 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 161 static 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 178 static 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 223 static 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. 265 static 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 284 template <class ELFT> uint32_t elf::calcMipsEFlags() { 285 std::vector<FileFlags> V; 286 for (InputFile *F : ObjectFiles) 287 V.push_back( 288 {F->getName(), cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags}); 289 if (V.empty()) 290 return 0; 291 checkFlags(V); 292 return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V); 293 } 294 295 static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) { 296 if (FpA == FpB) 297 return 0; 298 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY) 299 return 1; 300 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A && 301 FpA == Mips::Val_GNU_MIPS_ABI_FP_64) 302 return 1; 303 if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX) 304 return -1; 305 if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE || 306 FpA == Mips::Val_GNU_MIPS_ABI_FP_64 || 307 FpA == Mips::Val_GNU_MIPS_ABI_FP_64A) 308 return 1; 309 return -1; 310 } 311 312 static StringRef getMipsFpAbiName(uint8_t FpAbi) { 313 switch (FpAbi) { 314 case Mips::Val_GNU_MIPS_ABI_FP_ANY: 315 return "any"; 316 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE: 317 return "-mdouble-float"; 318 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE: 319 return "-msingle-float"; 320 case Mips::Val_GNU_MIPS_ABI_FP_SOFT: 321 return "-msoft-float"; 322 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64: 323 return "-mips32r2 -mfp64 (old)"; 324 case Mips::Val_GNU_MIPS_ABI_FP_XX: 325 return "-mfpxx"; 326 case Mips::Val_GNU_MIPS_ABI_FP_64: 327 return "-mgp32 -mfp64"; 328 case Mips::Val_GNU_MIPS_ABI_FP_64A: 329 return "-mgp32 -mfp64 -mno-odd-spreg"; 330 default: 331 return "unknown"; 332 } 333 } 334 335 uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, 336 StringRef FileName) { 337 if (compareMipsFpAbi(NewFlag, OldFlag) >= 0) 338 return NewFlag; 339 if (compareMipsFpAbi(OldFlag, NewFlag) < 0) 340 error("target floating point ABI '" + getMipsFpAbiName(OldFlag) + 341 "' is incompatible with '" + getMipsFpAbiName(NewFlag) + 342 "': " + FileName); 343 return OldFlag; 344 } 345 346 template <class ELFT> static bool isN32Abi(const InputFile *F) { 347 if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F)) 348 return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2; 349 return false; 350 } 351 352 bool elf::isMipsN32Abi(const InputFile *F) { 353 switch (Config->EKind) { 354 case ELF32LEKind: 355 return isN32Abi<ELF32LE>(F); 356 case ELF32BEKind: 357 return isN32Abi<ELF32BE>(F); 358 case ELF64LEKind: 359 return isN32Abi<ELF64LE>(F); 360 case ELF64BEKind: 361 return isN32Abi<ELF64BE>(F); 362 default: 363 llvm_unreachable("unknown Config->EKind"); 364 } 365 } 366 367 template uint32_t elf::calcMipsEFlags<ELF32LE>(); 368 template uint32_t elf::calcMipsEFlags<ELF32BE>(); 369 template uint32_t elf::calcMipsEFlags<ELF64LE>(); 370 template uint32_t elf::calcMipsEFlags<ELF64BE>(); 371