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