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 //===---------------------------------------------------------------------===//
14 #include "InputFiles.h"
15 #include "SymbolTable.h"
18 #include "lld/Common/ErrorHandler.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 assert(!Files.empty() && "expected non-empty file list");
70 uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
71 bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
72 bool Fp = Files[0].Flags & EF_MIPS_FP64;
74 for (const FileFlags &F : Files) {
75 if (Config->Is64 && F.Flags & EF_MIPS_MICROMIPS)
76 error(toString(F.File) + ": microMIPS 64-bit is not supported");
78 uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
80 error(toString(F.File) + ": ABI '" + getAbiName(ABI2) +
81 "' is incompatible with target ABI '" + getAbiName(ABI) + "'");
83 bool Nan2 = F.Flags & EF_MIPS_NAN2008;
85 error(toString(F.File) + ": -mnan=" + getNanName(Nan2) +
86 " is incompatible with target -mnan=" + getNanName(Nan));
88 bool Fp2 = F.Flags & EF_MIPS_FP64;
90 error(toString(F.File) + ": -mfp" + getFpName(Fp2) +
91 " is incompatible with target -mfp" + getFpName(Fp));
95 static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
97 for (const FileFlags &F : Files)
99 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
100 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
104 static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
105 // Check PIC/non-PIC compatibility.
106 bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
107 for (const FileFlags &F : Files.slice(1)) {
108 bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
109 if (IsPic && !IsPic2)
110 warn(toString(F.File) +
111 ": linking non-abicalls code with abicalls code " +
112 toString(Files[0].File));
113 if (!IsPic && IsPic2)
114 warn(toString(F.File) +
115 ": linking abicalls code with non-abicalls code " +
116 toString(Files[0].File));
119 // Compute the result PIC/non-PIC flag.
120 uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
121 for (const FileFlags &F : Files.slice(1))
122 Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
124 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
125 if (Ret & EF_MIPS_PIC)
130 static ArchTreeEdge ArchTree[] = {
131 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
132 // MIPS64R2 extensions.
133 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
134 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
135 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
136 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
137 // MIPS64 extensions.
138 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
139 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
140 {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
141 // MIPS V extensions.
142 {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
144 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
145 // MIPS IV extensions.
146 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
147 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
148 {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
149 // VR4100 extensions.
150 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
151 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
152 // MIPS III extensions.
153 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
154 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
155 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
156 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
157 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
158 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
159 {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
160 // MIPS32 extensions.
161 {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
162 // MIPS II extensions.
163 {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
164 {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
165 // MIPS I extensions.
166 {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
167 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
170 static bool isArchMatched(uint32_t New, uint32_t Res) {
173 if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))
175 if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))
177 for (const auto &Edge : ArchTree) {
178 if (Res == Edge.Child) {
187 static StringRef getMachName(uint32_t Flags) {
188 switch (Flags & EF_MIPS_MACH) {
189 case EF_MIPS_MACH_NONE:
191 case EF_MIPS_MACH_3900:
193 case EF_MIPS_MACH_4010:
195 case EF_MIPS_MACH_4100:
197 case EF_MIPS_MACH_4650:
199 case EF_MIPS_MACH_4120:
201 case EF_MIPS_MACH_4111:
203 case EF_MIPS_MACH_5400:
205 case EF_MIPS_MACH_5900:
207 case EF_MIPS_MACH_5500:
209 case EF_MIPS_MACH_9000:
211 case EF_MIPS_MACH_LS2E:
213 case EF_MIPS_MACH_LS2F:
215 case EF_MIPS_MACH_LS3A:
217 case EF_MIPS_MACH_OCTEON:
219 case EF_MIPS_MACH_OCTEON2:
221 case EF_MIPS_MACH_OCTEON3:
223 case EF_MIPS_MACH_SB1:
225 case EF_MIPS_MACH_XLR:
228 return "unknown machine";
232 static StringRef getArchName(uint32_t Flags) {
233 switch (Flags & EF_MIPS_ARCH) {
244 case EF_MIPS_ARCH_32:
246 case EF_MIPS_ARCH_64:
248 case EF_MIPS_ARCH_32R2:
250 case EF_MIPS_ARCH_64R2:
252 case EF_MIPS_ARCH_32R6:
254 case EF_MIPS_ARCH_64R6:
257 return "unknown arch";
261 static std::string getFullArchName(uint32_t Flags) {
262 StringRef Arch = getArchName(Flags);
263 StringRef Mach = getMachName(Flags);
266 return (Arch + " (" + Mach + ")").str();
269 // There are (arguably too) many MIPS ISAs out there. Their relationships
270 // can be represented as a forest. If all input files have ISAs which
271 // reachable by repeated proceeding from the single child to the parent,
272 // these input files are compatible. In that case we need to return "highest"
273 // ISA. If there are incompatible input files, we show an error.
274 // For example, mips1 is a "parent" of mips2 and such files are compatible.
275 // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
276 // are incompatible because nor mips3 is a parent for misp32, nor mips32
277 // is a parent for mips3.
278 static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
279 uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
281 for (const FileFlags &F : Files.slice(1)) {
282 uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
284 // Check ISA compatibility.
285 if (isArchMatched(New, Ret))
287 if (!isArchMatched(Ret, New)) {
288 error("incompatible target ISA:\n>>> " + toString(Files[0].File) + ": " +
289 getFullArchName(Ret) + "\n>>> " + toString(F.File) + ": " +
290 getFullArchName(New));
298 template <class ELFT> uint32_t elf::calcMipsEFlags() {
299 std::vector<FileFlags> V;
300 for (InputFile *F : ObjectFiles)
301 V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
305 return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
308 static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
311 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
313 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
314 FpA == Mips::Val_GNU_MIPS_ABI_FP_64)
316 if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
318 if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
319 FpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
320 FpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
325 static StringRef getMipsFpAbiName(uint8_t FpAbi) {
327 case Mips::Val_GNU_MIPS_ABI_FP_ANY:
329 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
330 return "-mdouble-float";
331 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
332 return "-msingle-float";
333 case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
334 return "-msoft-float";
335 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
336 return "-mgp32 -mfp64 (old)";
337 case Mips::Val_GNU_MIPS_ABI_FP_XX:
339 case Mips::Val_GNU_MIPS_ABI_FP_64:
340 return "-mgp32 -mfp64";
341 case Mips::Val_GNU_MIPS_ABI_FP_64A:
342 return "-mgp32 -mfp64 -mno-odd-spreg";
348 uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
349 StringRef FileName) {
350 if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
352 if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
353 error(FileName + ": floating point ABI '" + getMipsFpAbiName(NewFlag) +
354 "' is incompatible with target floating point ABI '" +
355 getMipsFpAbiName(OldFlag) + "'");
359 template <class ELFT> static bool isN32Abi(const InputFile *F) {
360 if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361 return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
365 bool elf::isMipsN32Abi(const InputFile *F) {
366 switch (Config->EKind) {
368 return isN32Abi<ELF32LE>(F);
370 return isN32Abi<ELF32BE>(F);
372 return isN32Abi<ELF64LE>(F);
374 return isN32Abi<ELF64BE>(F);
376 llvm_unreachable("unknown Config->EKind");
380 bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; }
382 bool elf::isMipsR6() {
383 uint32_t Arch = Config->EFlags & EF_MIPS_ARCH;
384 return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;
387 template uint32_t elf::calcMipsEFlags<ELF32LE>();
388 template uint32_t elf::calcMipsEFlags<ELF32BE>();
389 template uint32_t elf::calcMipsEFlags<ELF64LE>();
390 template uint32_t elf::calcMipsEFlags<ELF64BE>();