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