1 //===- MipsArchTree.cpp --------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===---------------------------------------------------------------------===//
9 // This file contains a helper function for the Writer.
11 //===---------------------------------------------------------------------===//
13 #include "InputFiles.h"
14 #include "SymbolTable.h"
17 #include "lld/Common/ErrorHandler.h"
18 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/Object/ELF.h"
20 #include "llvm/Support/MipsABIFlags.h"
23 using namespace llvm::object;
24 using namespace llvm::ELF;
27 using namespace lld::elf;
41 static StringRef getAbiName(uint32_t flags) {
51 case EF_MIPS_ABI_EABI32:
53 case EF_MIPS_ABI_EABI64:
60 static StringRef getNanName(bool isNan2008) {
61 return isNan2008 ? "2008" : "legacy";
64 static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
66 static void checkFlags(ArrayRef<FileFlags> files) {
67 assert(!files.empty() && "expected non-empty file list");
69 uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
70 bool nan = files[0].flags & EF_MIPS_NAN2008;
71 bool fp = files[0].flags & EF_MIPS_FP64;
73 for (const FileFlags &f : files) {
74 if (config->is64 && f.flags & EF_MIPS_MICROMIPS)
75 error(toString(f.file) + ": microMIPS 64-bit is not supported");
77 uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
79 error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
80 "' is incompatible with target ABI '" + getAbiName(abi) + "'");
82 bool nan2 = f.flags & EF_MIPS_NAN2008;
84 error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
85 " is incompatible with target -mnan=" + getNanName(nan));
87 bool fp2 = f.flags & EF_MIPS_FP64;
89 error(toString(f.file) + ": -mfp" + getFpName(fp2) +
90 " is incompatible with target -mfp" + getFpName(fp));
94 static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
96 for (const FileFlags &f : files)
98 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
99 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
103 static uint32_t getPicFlags(ArrayRef<FileFlags> files) {
104 // Check PIC/non-PIC compatibility.
105 bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
106 for (const FileFlags &f : files.slice(1)) {
107 bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
108 if (isPic && !isPic2)
109 warn(toString(f.file) +
110 ": linking non-abicalls code with abicalls code " +
111 toString(files[0].file));
112 if (!isPic && isPic2)
113 warn(toString(f.file) +
114 ": linking abicalls code with non-abicalls code " +
115 toString(files[0].file));
118 // Compute the result PIC/non-PIC flag.
119 uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
120 for (const FileFlags &f : files.slice(1))
121 ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
123 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
124 if (ret & EF_MIPS_PIC)
129 static ArchTreeEdge archTree[] = {
130 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
131 // MIPS64R2 extensions.
132 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
133 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
134 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
135 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
136 // MIPS64 extensions.
137 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
138 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
139 {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
140 // MIPS V extensions.
141 {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
143 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
144 // MIPS IV extensions.
145 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
146 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
147 {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
148 // VR4100 extensions.
149 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
150 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
151 // MIPS III extensions.
152 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
153 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
154 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
155 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
156 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
157 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
158 {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
159 // MIPS32 extensions.
160 {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
161 // MIPS II extensions.
162 {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
163 {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
164 // MIPS I extensions.
165 {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
166 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
169 static bool isArchMatched(uint32_t newFlags, uint32_t res) {
172 if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
174 if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
176 for (const auto &edge : archTree) {
177 if (res == edge.child) {
186 static StringRef getMachName(uint32_t flags) {
187 switch (flags & EF_MIPS_MACH) {
188 case EF_MIPS_MACH_NONE:
190 case EF_MIPS_MACH_3900:
192 case EF_MIPS_MACH_4010:
194 case EF_MIPS_MACH_4100:
196 case EF_MIPS_MACH_4650:
198 case EF_MIPS_MACH_4120:
200 case EF_MIPS_MACH_4111:
202 case EF_MIPS_MACH_5400:
204 case EF_MIPS_MACH_5900:
206 case EF_MIPS_MACH_5500:
208 case EF_MIPS_MACH_9000:
210 case EF_MIPS_MACH_LS2E:
212 case EF_MIPS_MACH_LS2F:
214 case EF_MIPS_MACH_LS3A:
216 case EF_MIPS_MACH_OCTEON:
218 case EF_MIPS_MACH_OCTEON2:
220 case EF_MIPS_MACH_OCTEON3:
222 case EF_MIPS_MACH_SB1:
224 case EF_MIPS_MACH_XLR:
227 return "unknown machine";
231 static StringRef getArchName(uint32_t flags) {
232 switch (flags & EF_MIPS_ARCH) {
243 case EF_MIPS_ARCH_32:
245 case EF_MIPS_ARCH_64:
247 case EF_MIPS_ARCH_32R2:
249 case EF_MIPS_ARCH_64R2:
251 case EF_MIPS_ARCH_32R6:
253 case EF_MIPS_ARCH_64R6:
256 return "unknown arch";
260 static std::string getFullArchName(uint32_t flags) {
261 StringRef arch = getArchName(flags);
262 StringRef mach = getMachName(flags);
265 return (arch + " (" + mach + ")").str();
268 // There are (arguably too) many MIPS ISAs out there. Their relationships
269 // can be represented as a forest. If all input files have ISAs which
270 // reachable by repeated proceeding from the single child to the parent,
271 // these input files are compatible. In that case we need to return "highest"
272 // ISA. If there are incompatible input files, we show an error.
273 // For example, mips1 is a "parent" of mips2 and such files are compatible.
274 // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
275 // are incompatible because nor mips3 is a parent for misp32, nor mips32
276 // is a parent for mips3.
277 static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
278 uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
280 for (const FileFlags &f : files.slice(1)) {
281 uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
283 // Check ISA compatibility.
284 if (isArchMatched(newFlags, ret))
286 if (!isArchMatched(ret, newFlags)) {
287 error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
288 getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
289 getFullArchName(newFlags));
297 template <class ELFT> uint32_t elf::calcMipsEFlags() {
298 std::vector<FileFlags> v;
299 for (InputFile *f : objectFiles)
300 v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
302 // If we don't have any input files, we'll have to rely on the information
303 // we can derive from emulation information, since this at least gets us
305 if (config->emulation.empty() || config->is64)
307 return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
310 return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
313 static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
316 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
318 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
319 fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
321 if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
323 if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
324 fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
325 fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
330 static StringRef getMipsFpAbiName(uint8_t fpAbi) {
332 case Mips::Val_GNU_MIPS_ABI_FP_ANY:
334 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
335 return "-mdouble-float";
336 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
337 return "-msingle-float";
338 case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
339 return "-msoft-float";
340 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
341 return "-mgp32 -mfp64 (old)";
342 case Mips::Val_GNU_MIPS_ABI_FP_XX:
344 case Mips::Val_GNU_MIPS_ABI_FP_64:
345 return "-mgp32 -mfp64";
346 case Mips::Val_GNU_MIPS_ABI_FP_64A:
347 return "-mgp32 -mfp64 -mno-odd-spreg";
353 uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
354 StringRef fileName) {
355 if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
357 if (compareMipsFpAbi(oldFlag, newFlag) < 0)
358 error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
359 "' is incompatible with target floating point ABI '" +
360 getMipsFpAbiName(oldFlag) + "'");
364 template <class ELFT> static bool isN32Abi(const InputFile *f) {
365 if (auto *ef = dyn_cast<ELFFileBase>(f))
366 return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
370 bool elf::isMipsN32Abi(const InputFile *f) {
371 switch (config->ekind) {
373 return isN32Abi<ELF32LE>(f);
375 return isN32Abi<ELF32BE>(f);
377 return isN32Abi<ELF64LE>(f);
379 return isN32Abi<ELF64BE>(f);
381 llvm_unreachable("unknown Config->EKind");
385 bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
387 bool elf::isMipsR6() {
388 uint32_t arch = config->eflags & EF_MIPS_ARCH;
389 return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
392 template uint32_t elf::calcMipsEFlags<ELF32LE>();
393 template uint32_t elf::calcMipsEFlags<ELF32BE>();
394 template uint32_t elf::calcMipsEFlags<ELF64LE>();
395 template uint32_t elf::calcMipsEFlags<ELF64BE>();