• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Object/ELF.h"
20 #include "llvm/Support/MipsABIFlags.h"
21 
22 using namespace llvm;
23 using namespace llvm::object;
24 using namespace llvm::ELF;
25 
26 using namespace lld;
27 using namespace lld::elf;
28 
29 namespace {
30 struct ArchTreeEdge {
31   uint32_t child;
32   uint32_t parent;
33 };
34 
35 struct FileFlags {
36   InputFile *file;
37   uint32_t flags;
38 };
39 } // namespace
40 
getAbiName(uint32_t flags)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";
57   }
58 }
59 
getNanName(bool isNan2008)60 static StringRef getNanName(bool isNan2008) {
61   return isNan2008 ? "2008" : "legacy";
62 }
63 
getFpName(bool isFp64)64 static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
65 
checkFlags(ArrayRef<FileFlags> files)66 static void checkFlags(ArrayRef<FileFlags> files) {
67   assert(!files.empty() && "expected non-empty file list");
68 
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;
72 
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");
76 
77     uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
78     if (abi != abi2)
79       error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
80             "' is incompatible with target ABI '" + getAbiName(abi) + "'");
81 
82     bool nan2 = f.flags & EF_MIPS_NAN2008;
83     if (nan != nan2)
84       error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
85             " is incompatible with target -mnan=" + getNanName(nan));
86 
87     bool fp2 = f.flags & EF_MIPS_FP64;
88     if (fp != fp2)
89       error(toString(f.file) + ": -mfp" + getFpName(fp2) +
90             " is incompatible with target -mfp" + getFpName(fp));
91   }
92 }
93 
getMiscFlags(ArrayRef<FileFlags> files)94 static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
95   uint32_t ret = 0;
96   for (const FileFlags &f : files)
97     ret |= f.flags &
98            (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
99             EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
100   return ret;
101 }
102 
getPicFlags(ArrayRef<FileFlags> files)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));
116   }
117 
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);
122 
123   // PIC code is inherently CPIC and may not set CPIC flag explicitly.
124   if (ret & EF_MIPS_PIC)
125     ret |= EF_MIPS_CPIC;
126   return ret;
127 }
128 
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},
142     // R5000 extensions.
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},
167 };
168 
isArchMatched(uint32_t newFlags,uint32_t res)169 static bool isArchMatched(uint32_t newFlags, uint32_t res) {
170   if (newFlags == res)
171     return true;
172   if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
173     return true;
174   if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
175     return true;
176   for (const auto &edge : archTree) {
177     if (res == edge.child) {
178       res = edge.parent;
179       if (res == newFlags)
180         return true;
181     }
182   }
183   return false;
184 }
185 
getMachName(uint32_t flags)186 static StringRef getMachName(uint32_t flags) {
187   switch (flags & EF_MIPS_MACH) {
188   case EF_MIPS_MACH_NONE:
189     return "";
190   case EF_MIPS_MACH_3900:
191     return "r3900";
192   case EF_MIPS_MACH_4010:
193     return "r4010";
194   case EF_MIPS_MACH_4100:
195     return "r4100";
196   case EF_MIPS_MACH_4650:
197     return "r4650";
198   case EF_MIPS_MACH_4120:
199     return "r4120";
200   case EF_MIPS_MACH_4111:
201     return "r4111";
202   case EF_MIPS_MACH_5400:
203     return "vr5400";
204   case EF_MIPS_MACH_5900:
205     return "vr5900";
206   case EF_MIPS_MACH_5500:
207     return "vr5500";
208   case EF_MIPS_MACH_9000:
209     return "rm9000";
210   case EF_MIPS_MACH_LS2E:
211     return "loongson2e";
212   case EF_MIPS_MACH_LS2F:
213     return "loongson2f";
214   case EF_MIPS_MACH_LS3A:
215     return "loongson3a";
216   case EF_MIPS_MACH_OCTEON:
217     return "octeon";
218   case EF_MIPS_MACH_OCTEON2:
219     return "octeon2";
220   case EF_MIPS_MACH_OCTEON3:
221     return "octeon3";
222   case EF_MIPS_MACH_SB1:
223     return "sb1";
224   case EF_MIPS_MACH_XLR:
225     return "xlr";
226   default:
227     return "unknown machine";
228   }
229 }
230 
getArchName(uint32_t flags)231 static StringRef getArchName(uint32_t flags) {
232   switch (flags & EF_MIPS_ARCH) {
233   case EF_MIPS_ARCH_1:
234     return "mips1";
235   case EF_MIPS_ARCH_2:
236     return "mips2";
237   case EF_MIPS_ARCH_3:
238     return "mips3";
239   case EF_MIPS_ARCH_4:
240     return "mips4";
241   case EF_MIPS_ARCH_5:
242     return "mips5";
243   case EF_MIPS_ARCH_32:
244     return "mips32";
245   case EF_MIPS_ARCH_64:
246     return "mips64";
247   case EF_MIPS_ARCH_32R2:
248     return "mips32r2";
249   case EF_MIPS_ARCH_64R2:
250     return "mips64r2";
251   case EF_MIPS_ARCH_32R6:
252     return "mips32r6";
253   case EF_MIPS_ARCH_64R6:
254     return "mips64r6";
255   default:
256     return "unknown arch";
257   }
258 }
259 
getFullArchName(uint32_t flags)260 static std::string getFullArchName(uint32_t flags) {
261   StringRef arch = getArchName(flags);
262   StringRef mach = getMachName(flags);
263   if (mach.empty())
264     return arch.str();
265   return (arch + " (" + mach + ")").str();
266 }
267 
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.
getArchFlags(ArrayRef<FileFlags> files)277 static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
278   uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
279 
280   for (const FileFlags &f : files.slice(1)) {
281     uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
282 
283     // Check ISA compatibility.
284     if (isArchMatched(newFlags, ret))
285       continue;
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));
290       return 0;
291     }
292     ret = newFlags;
293   }
294   return ret;
295 }
296 
calcMipsEFlags()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});
301   if (v.empty()) {
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
304     // ABI.
305     if (config->emulation.empty() || config->is64)
306       return 0;
307     return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
308   }
309   checkFlags(v);
310   return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
311 }
312 
compareMipsFpAbi(uint8_t fpA,uint8_t fpB)313 static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
314   if (fpA == fpB)
315     return 0;
316   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
317     return 1;
318   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
319       fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
320     return 1;
321   if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
322     return -1;
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)
326     return 1;
327   return -1;
328 }
329 
getMipsFpAbiName(uint8_t fpAbi)330 static StringRef getMipsFpAbiName(uint8_t fpAbi) {
331   switch (fpAbi) {
332   case Mips::Val_GNU_MIPS_ABI_FP_ANY:
333     return "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:
343     return "-mfpxx";
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";
348   default:
349     return "unknown";
350   }
351 }
352 
getMipsFpAbiFlag(uint8_t oldFlag,uint8_t newFlag,StringRef fileName)353 uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
354                               StringRef fileName) {
355   if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
356     return newFlag;
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) + "'");
361   return oldFlag;
362 }
363 
isN32Abi(const InputFile * f)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;
367   return false;
368 }
369 
isMipsN32Abi(const InputFile * f)370 bool elf::isMipsN32Abi(const InputFile *f) {
371   switch (config->ekind) {
372   case ELF32LEKind:
373     return isN32Abi<ELF32LE>(f);
374   case ELF32BEKind:
375     return isN32Abi<ELF32BE>(f);
376   case ELF64LEKind:
377     return isN32Abi<ELF64LE>(f);
378   case ELF64BEKind:
379     return isN32Abi<ELF64BE>(f);
380   default:
381     llvm_unreachable("unknown Config->EKind");
382   }
383 }
384 
isMicroMips()385 bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
386 
isMipsR6()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;
390 }
391 
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>();
396