1 //===- MipsArchTree.cpp --------------------------------------------------===//
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===---------------------------------------------------------------------===//
10 // This file contains a helper function for the Writer.
12 //===---------------------------------------------------------------------===//
15 #include "InputFiles.h"
16 #include "SymbolTable.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/Object/ELF.h"
21 #include "llvm/Support/MipsABIFlags.h"
24 using namespace llvm::object;
25 using namespace llvm::ELF;
28 using namespace lld::elf;
42 static StringRef getAbiName(uint32_t Flags) {
52 case EF_MIPS_ABI_EABI32:
54 case EF_MIPS_ABI_EABI64:
61 static StringRef getNanName(bool IsNan2008) {
62 return IsNan2008 ? "2008" : "legacy";
65 static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }
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;
72 for (const FileFlags &F : Files.slice(1)) {
73 uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
75 error("target ABI '" + getAbiName(ABI) + "' is incompatible with '" +
76 getAbiName(ABI2) + "': " + F.Filename);
78 bool Nan2 = F.Flags & EF_MIPS_NAN2008;
80 error("target -mnan=" + getNanName(Nan) + " is incompatible with -mnan=" +
81 getNanName(Nan2) + ": " + F.Filename);
83 bool Fp2 = F.Flags & EF_MIPS_FP64;
85 error("target -mfp" + getFpName(Fp) + " is incompatible with -mfp" +
86 getFpName(Fp2) + ": " + F.Filename);
90 static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
92 for (const FileFlags &F : Files)
94 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
95 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
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);
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);
115 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
116 if (Ret & EF_MIPS_PIC)
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},
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},
161 static bool isArchMatched(uint32_t New, uint32_t Res) {
164 if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))
166 if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))
168 for (const auto &Edge : ArchTree) {
169 if (Res == Edge.Child) {
178 static StringRef getMachName(uint32_t Flags) {
179 switch (Flags & EF_MIPS_MACH) {
180 case EF_MIPS_MACH_NONE:
182 case EF_MIPS_MACH_3900:
184 case EF_MIPS_MACH_4010:
186 case EF_MIPS_MACH_4100:
188 case EF_MIPS_MACH_4650:
190 case EF_MIPS_MACH_4120:
192 case EF_MIPS_MACH_4111:
194 case EF_MIPS_MACH_5400:
196 case EF_MIPS_MACH_5900:
198 case EF_MIPS_MACH_5500:
200 case EF_MIPS_MACH_9000:
202 case EF_MIPS_MACH_LS2E:
204 case EF_MIPS_MACH_LS2F:
206 case EF_MIPS_MACH_LS3A:
208 case EF_MIPS_MACH_OCTEON:
210 case EF_MIPS_MACH_OCTEON2:
212 case EF_MIPS_MACH_OCTEON3:
214 case EF_MIPS_MACH_SB1:
216 case EF_MIPS_MACH_XLR:
219 return "unknown machine";
223 static StringRef getArchName(uint32_t Flags) {
224 StringRef S = getMachName(Flags);
228 switch (Flags & EF_MIPS_ARCH) {
239 case EF_MIPS_ARCH_32:
241 case EF_MIPS_ARCH_64:
243 case EF_MIPS_ARCH_32R2:
245 case EF_MIPS_ARCH_64R2:
247 case EF_MIPS_ARCH_32R6:
249 case EF_MIPS_ARCH_64R6:
252 return "unknown arch";
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);
268 for (const FileFlags &F : Files.slice(1)) {
269 uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
271 // Check ISA compatibility.
272 if (isArchMatched(New, Ret))
274 if (!isArchMatched(Ret, New)) {
275 error("target ISA '" + getArchName(Ret) + "' is incompatible with '" +
276 getArchName(New) + "': " + F.Filename);
284 template <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});
291 return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
294 static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
297 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
299 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
300 FpA == Mips::Val_GNU_MIPS_ABI_FP_64)
302 if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
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)
311 static StringRef getMipsFpAbiName(uint8_t FpAbi) {
313 case Mips::Val_GNU_MIPS_ABI_FP_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:
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";
334 uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
335 StringRef FileName) {
336 if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
338 if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
339 error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
340 "' is incompatible with '" + getMipsFpAbiName(NewFlag) +
345 template <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;
351 bool elf::isMipsN32Abi(const InputFile *F) {
352 switch (Config->EKind) {
354 return isN32Abi<ELF32LE>(F);
356 return isN32Abi<ELF32BE>(F);
358 return isN32Abi<ELF64LE>(F);
360 return isN32Abi<ELF64BE>(F);
362 llvm_unreachable("unknown Config->EKind");
366 template uint32_t elf::getMipsEFlags<ELF32LE>();
367 template uint32_t elf::getMipsEFlags<ELF32BE>();
368 template uint32_t elf::getMipsEFlags<ELF64LE>();
369 template uint32_t elf::getMipsEFlags<ELF64BE>();