xref: /freebsd/contrib/llvm-project/lld/ELF/Arch/MipsArchTree.cpp (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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 "Writer.h"
16 
17 #include "lld/Common/ErrorHandler.h"
18 #include "llvm/BinaryFormat/ELF.h"
19 #include "llvm/Support/MipsABIFlags.h"
20 
21 using namespace llvm;
22 using namespace llvm::object;
23 using namespace llvm::ELF;
24 
25 using namespace lld;
26 using namespace lld::elf;
27 
28 namespace {
29 struct ArchTreeEdge {
30   uint32_t child;
31   uint32_t parent;
32 };
33 
34 struct FileFlags {
35   InputFile *file;
36   uint32_t flags;
37 };
38 } // namespace
39 
40 static StringRef getAbiName(uint32_t flags) {
41   switch (flags) {
42   case 0:
43     return "n64";
44   case EF_MIPS_ABI2:
45     return "n32";
46   case EF_MIPS_ABI_O32:
47     return "o32";
48   case EF_MIPS_ABI_O64:
49     return "o64";
50   case EF_MIPS_ABI_EABI32:
51     return "eabi32";
52   case EF_MIPS_ABI_EABI64:
53     return "eabi64";
54   default:
55     return "unknown";
56   }
57 }
58 
59 static StringRef getNanName(bool isNan2008) {
60   return isNan2008 ? "2008" : "legacy";
61 }
62 
63 static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
64 
65 static void checkFlags(ArrayRef<FileFlags> files) {
66   assert(!files.empty() && "expected non-empty file list");
67 
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;
71 
72   for (const FileFlags &f : files) {
73     if (config->is64 && f.flags & EF_MIPS_MICROMIPS)
74       error(toString(f.file) + ": microMIPS 64-bit is not supported");
75 
76     uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
77     if (abi != abi2)
78       error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
79             "' is incompatible with target ABI '" + getAbiName(abi) + "'");
80 
81     bool nan2 = f.flags & EF_MIPS_NAN2008;
82     if (nan != nan2)
83       error(toString(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       error(toString(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(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(toString(f.file) +
109            ": linking non-abicalls code with abicalls code " +
110            toString(files[0].file));
111     if (!isPic && isPic2)
112       warn(toString(f.file) +
113            ": linking abicalls code with non-abicalls code " +
114            toString(files[0].file));
115   }
116 
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);
121 
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;
126 }
127 
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},
166 };
167 
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;
180     }
181   }
182   return false;
183 }
184 
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";
227   }
228 }
229 
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";
256   }
257 }
258 
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();
265 }
266 
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(ArrayRef<FileFlags> files) {
277   uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
278 
279   for (const FileFlags &f : files.slice(1)) {
280     uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
281 
282     // Check ISA compatibility.
283     if (isArchMatched(newFlags, ret))
284       continue;
285     if (!isArchMatched(ret, newFlags)) {
286       error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
287             getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
288             getFullArchName(newFlags));
289       return 0;
290     }
291     ret = newFlags;
292   }
293   return ret;
294 }
295 
296 template <class ELFT> uint32_t elf::calcMipsEFlags() {
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 (config->emulation.empty() || config->is64)
305       return 0;
306     return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
307   }
308   checkFlags(v);
309   return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
310 }
311 
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;
327 }
328 
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";
349   }
350 }
351 
352 uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
353                               StringRef fileName) {
354   if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
355     return newFlag;
356   if (compareMipsFpAbi(oldFlag, newFlag) < 0)
357     error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
358           "' is incompatible with target floating point ABI '" +
359           getMipsFpAbiName(oldFlag) + "'");
360   return oldFlag;
361 }
362 
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;
367 }
368 
369 bool elf::isMipsN32Abi(const InputFile *f) {
370   switch (config->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 Config->EKind");
381   }
382 }
383 
384 bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
385 
386 bool elf::isMipsR6() {
387   uint32_t arch = config->eflags & EF_MIPS_ARCH;
388   return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
389 }
390 
391 template uint32_t elf::calcMipsEFlags<ELF32LE>();
392 template uint32_t elf::calcMipsEFlags<ELF32BE>();
393 template uint32_t elf::calcMipsEFlags<ELF64LE>();
394 template uint32_t elf::calcMipsEFlags<ELF64BE>();
395