[Xtensa] Implement Code Density Option. (#119639)
[llvm-project.git] / lld / ELF / Arch / MipsArchTree.cpp
blob197cb30cdb8a5641ae315e19985cf3d81220584a
1 //===- MipsArchTree.cpp --------------------------------------------------===//
2 //
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
6 //
7 //===---------------------------------------------------------------------===//
8 //
9 // This file contains a helper function for the Writer.
11 //===---------------------------------------------------------------------===//
13 #include "InputFiles.h"
14 #include "SymbolTable.h"
15 #include "Target.h"
16 #include "Writer.h"
18 #include "lld/Common/ErrorHandler.h"
19 #include "llvm/BinaryFormat/ELF.h"
20 #include "llvm/Support/MipsABIFlags.h"
22 using namespace llvm;
23 using namespace llvm::object;
24 using namespace llvm::ELF;
26 using namespace lld;
27 using namespace lld::elf;
29 namespace {
30 struct ArchTreeEdge {
31 uint32_t child;
32 uint32_t parent;
35 struct FileFlags {
36 InputFile *file;
37 uint32_t flags;
39 } // namespace
41 static StringRef getAbiName(uint32_t flags) {
42 switch (flags) {
43 case 0:
44 return "n64";
45 case EF_MIPS_ABI2:
46 return "n32";
47 case EF_MIPS_ABI_O32:
48 return "o32";
49 case EF_MIPS_ABI_O64:
50 return "o64";
51 case EF_MIPS_ABI_EABI32:
52 return "eabi32";
53 case EF_MIPS_ABI_EABI64:
54 return "eabi64";
55 default:
56 return "unknown";
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(Ctx &ctx, 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 (ctx.arg.is64 && f.flags & EF_MIPS_MICROMIPS)
75 Err(ctx) << f.file << ": microMIPS 64-bit is not supported";
77 uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
78 if (abi != abi2)
79 Err(ctx) << f.file << ": ABI '" << getAbiName(abi2)
80 << "' is incompatible with target ABI '" << getAbiName(abi)
81 << "'";
83 bool nan2 = f.flags & EF_MIPS_NAN2008;
84 if (nan != nan2)
85 Err(ctx) << f.file << ": -mnan=" << getNanName(nan2)
86 << " is incompatible with target -mnan=" << getNanName(nan);
88 bool fp2 = f.flags & EF_MIPS_FP64;
89 if (fp != fp2)
90 Err(ctx) << f.file << ": -mfp" << getFpName(fp2)
91 << " is incompatible with target -mfp" << getFpName(fp);
95 static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
96 uint32_t ret = 0;
97 for (const FileFlags &f : files)
98 ret |= f.flags &
99 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
100 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
101 return ret;
104 static uint32_t getPicFlags(Ctx &ctx, 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(ctx) << f.file << ": linking non-abicalls code with abicalls code "
111 << files[0].file;
112 if (!isPic && isPic2)
113 Warn(ctx) << f.file << ": linking abicalls code with non-abicalls code "
114 << files[0].file;
117 // Compute the result PIC/non-PIC flag.
118 uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
119 for (const FileFlags &f : files.slice(1))
120 ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
122 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
123 if (ret & EF_MIPS_PIC)
124 ret |= EF_MIPS_CPIC;
125 return ret;
128 static ArchTreeEdge archTree[] = {
129 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
130 // MIPS64R2 extensions.
131 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
132 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
133 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
134 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
135 // MIPS64 extensions.
136 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
137 {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
138 {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
139 // MIPS V extensions.
140 {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
141 // R5000 extensions.
142 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
143 // MIPS IV extensions.
144 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
145 {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
146 {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
147 // VR4100 extensions.
148 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
149 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
150 // MIPS III extensions.
151 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
152 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
153 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
154 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
155 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
156 {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
157 {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
158 // MIPS32 extensions.
159 {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
160 // MIPS II extensions.
161 {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
162 {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
163 // MIPS I extensions.
164 {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
165 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
168 static bool isArchMatched(uint32_t newFlags, uint32_t res) {
169 if (newFlags == res)
170 return true;
171 if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
172 return true;
173 if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
174 return true;
175 for (const auto &edge : archTree) {
176 if (res == edge.child) {
177 res = edge.parent;
178 if (res == newFlags)
179 return true;
182 return false;
185 static StringRef getMachName(uint32_t flags) {
186 switch (flags & EF_MIPS_MACH) {
187 case EF_MIPS_MACH_NONE:
188 return "";
189 case EF_MIPS_MACH_3900:
190 return "r3900";
191 case EF_MIPS_MACH_4010:
192 return "r4010";
193 case EF_MIPS_MACH_4100:
194 return "r4100";
195 case EF_MIPS_MACH_4650:
196 return "r4650";
197 case EF_MIPS_MACH_4120:
198 return "r4120";
199 case EF_MIPS_MACH_4111:
200 return "r4111";
201 case EF_MIPS_MACH_5400:
202 return "vr5400";
203 case EF_MIPS_MACH_5900:
204 return "vr5900";
205 case EF_MIPS_MACH_5500:
206 return "vr5500";
207 case EF_MIPS_MACH_9000:
208 return "rm9000";
209 case EF_MIPS_MACH_LS2E:
210 return "loongson2e";
211 case EF_MIPS_MACH_LS2F:
212 return "loongson2f";
213 case EF_MIPS_MACH_LS3A:
214 return "loongson3a";
215 case EF_MIPS_MACH_OCTEON:
216 return "octeon";
217 case EF_MIPS_MACH_OCTEON2:
218 return "octeon2";
219 case EF_MIPS_MACH_OCTEON3:
220 return "octeon3";
221 case EF_MIPS_MACH_SB1:
222 return "sb1";
223 case EF_MIPS_MACH_XLR:
224 return "xlr";
225 default:
226 return "unknown machine";
230 static StringRef getArchName(uint32_t flags) {
231 switch (flags & EF_MIPS_ARCH) {
232 case EF_MIPS_ARCH_1:
233 return "mips1";
234 case EF_MIPS_ARCH_2:
235 return "mips2";
236 case EF_MIPS_ARCH_3:
237 return "mips3";
238 case EF_MIPS_ARCH_4:
239 return "mips4";
240 case EF_MIPS_ARCH_5:
241 return "mips5";
242 case EF_MIPS_ARCH_32:
243 return "mips32";
244 case EF_MIPS_ARCH_64:
245 return "mips64";
246 case EF_MIPS_ARCH_32R2:
247 return "mips32r2";
248 case EF_MIPS_ARCH_64R2:
249 return "mips64r2";
250 case EF_MIPS_ARCH_32R6:
251 return "mips32r6";
252 case EF_MIPS_ARCH_64R6:
253 return "mips64r6";
254 default:
255 return "unknown arch";
259 static std::string getFullArchName(uint32_t flags) {
260 StringRef arch = getArchName(flags);
261 StringRef mach = getMachName(flags);
262 if (mach.empty())
263 return arch.str();
264 return (arch + " (" + mach + ")").str();
267 // There are (arguably too) many MIPS ISAs out there. Their relationships
268 // can be represented as a forest. If all input files have ISAs which
269 // reachable by repeated proceeding from the single child to the parent,
270 // these input files are compatible. In that case we need to return "highest"
271 // ISA. If there are incompatible input files, we show an error.
272 // For example, mips1 is a "parent" of mips2 and such files are compatible.
273 // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
274 // are incompatible because nor mips3 is a parent for misp32, nor mips32
275 // is a parent for mips3.
276 static uint32_t getArchFlags(Ctx &ctx, ArrayRef<FileFlags> files) {
277 uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
279 for (const FileFlags &f : files.slice(1)) {
280 uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
282 // Check ISA compatibility.
283 if (isArchMatched(newFlags, ret))
284 continue;
285 if (!isArchMatched(ret, newFlags)) {
286 Err(ctx) << "incompatible target ISA:\n>>> " << files[0].file << ": "
287 << getFullArchName(ret) << "\n>>> " << f.file << ": "
288 << getFullArchName(newFlags);
289 return 0;
291 ret = newFlags;
293 return ret;
296 template <class ELFT> uint32_t elf::calcMipsEFlags(Ctx &ctx) {
297 std::vector<FileFlags> v;
298 for (InputFile *f : ctx.objectFiles)
299 v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags});
300 if (v.empty()) {
301 // If we don't have any input files, we'll have to rely on the information
302 // we can derive from emulation information, since this at least gets us
303 // ABI.
304 if (ctx.arg.emulation.empty() || ctx.arg.is64)
305 return 0;
306 return ctx.arg.mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
308 checkFlags(ctx, v);
309 return getMiscFlags(v) | getPicFlags(ctx, v) | getArchFlags(ctx, v);
312 static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
313 if (fpA == fpB)
314 return 0;
315 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
316 return 1;
317 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
318 fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
319 return 1;
320 if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
321 return -1;
322 if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
323 fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
324 fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
325 return 1;
326 return -1;
329 static StringRef getMipsFpAbiName(uint8_t fpAbi) {
330 switch (fpAbi) {
331 case Mips::Val_GNU_MIPS_ABI_FP_ANY:
332 return "any";
333 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
334 return "-mdouble-float";
335 case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
336 return "-msingle-float";
337 case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
338 return "-msoft-float";
339 case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
340 return "-mgp32 -mfp64 (old)";
341 case Mips::Val_GNU_MIPS_ABI_FP_XX:
342 return "-mfpxx";
343 case Mips::Val_GNU_MIPS_ABI_FP_64:
344 return "-mgp32 -mfp64";
345 case Mips::Val_GNU_MIPS_ABI_FP_64A:
346 return "-mgp32 -mfp64 -mno-odd-spreg";
347 default:
348 return "unknown";
352 uint8_t elf::getMipsFpAbiFlag(Ctx &ctx, InputFile *file, uint8_t oldFlag,
353 uint8_t newFlag) {
354 if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
355 return newFlag;
356 if (compareMipsFpAbi(oldFlag, newFlag) < 0)
357 Err(ctx) << file << ": floating point ABI '" << getMipsFpAbiName(newFlag)
358 << "' is incompatible with target floating point ABI '"
359 << getMipsFpAbiName(oldFlag) << "'";
360 return oldFlag;
363 template <class ELFT> static bool isN32Abi(const InputFile &f) {
364 if (auto *ef = dyn_cast<ELFFileBase>(&f))
365 return ef->template getObj<ELFT>().getHeader().e_flags & EF_MIPS_ABI2;
366 return false;
369 bool elf::isMipsN32Abi(Ctx &ctx, const InputFile &f) {
370 switch (ctx.arg.ekind) {
371 case ELF32LEKind:
372 return isN32Abi<ELF32LE>(f);
373 case ELF32BEKind:
374 return isN32Abi<ELF32BE>(f);
375 case ELF64LEKind:
376 return isN32Abi<ELF64LE>(f);
377 case ELF64BEKind:
378 return isN32Abi<ELF64BE>(f);
379 default:
380 llvm_unreachable("unknown ctx.arg.ekind");
384 bool elf::isMicroMips(Ctx &ctx) { return ctx.arg.eflags & EF_MIPS_MICROMIPS; }
386 bool elf::isMipsR6(Ctx &ctx) {
387 uint32_t arch = ctx.arg.eflags & EF_MIPS_ARCH;
388 return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
391 template uint32_t elf::calcMipsEFlags<ELF32LE>(Ctx &);
392 template uint32_t elf::calcMipsEFlags<ELF32BE>(Ctx &);
393 template uint32_t elf::calcMipsEFlags<ELF64LE>(Ctx &);
394 template uint32_t elf::calcMipsEFlags<ELF64BE>(Ctx &);