MipsArchTree.cpp revision 327952
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 "InputFiles.h"
15#include "SymbolTable.h"
16#include "Writer.h"
17
18#include "lld/Common/ErrorHandler.h"
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  InputFile *File;
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) + "': " + toString(F.File));
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) + ": " + toString(F.File));
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) + ": " + toString(F.File));
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 " + toString(Files[0].File) +
106           " with non-abicalls file: " + toString(F.File));
107    if (!IsPic && IsPic2)
108      warn("linking non-abicalls code " + toString(Files[0].File) +
109           " with abicalls file: " + toString(F.File));
110  }
111
112  // Compute the result PIC/non-PIC flag.
113  uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
114  for (const FileFlags &F : Files.slice(1))
115    Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
116
117  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
118  if (Ret & EF_MIPS_PIC)
119    Ret |= EF_MIPS_CPIC;
120  return Ret;
121}
122
123static ArchTreeEdge ArchTree[] = {
124    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
125    // MIPS64R2 extensions.
126    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
127    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
128    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
129    {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
130    // MIPS64 extensions.
131    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
132    {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
133    {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
134    // MIPS V extensions.
135    {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
136    // R5000 extensions.
137    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
138    // MIPS IV extensions.
139    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
140    {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
141    {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
142    // VR4100 extensions.
143    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
144    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
145    // MIPS III extensions.
146    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
147    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
148    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
149    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
150    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
151    {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
152    {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
153    // MIPS32 extensions.
154    {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
155    // MIPS II extensions.
156    {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
157    {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
158    // MIPS I extensions.
159    {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
160    {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
161};
162
163static bool isArchMatched(uint32_t New, uint32_t Res) {
164  if (New == Res)
165    return true;
166  if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))
167    return true;
168  if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))
169    return true;
170  for (const auto &Edge : ArchTree) {
171    if (Res == Edge.Child) {
172      Res = Edge.Parent;
173      if (Res == New)
174        return true;
175    }
176  }
177  return false;
178}
179
180static StringRef getMachName(uint32_t Flags) {
181  switch (Flags & EF_MIPS_MACH) {
182  case EF_MIPS_MACH_NONE:
183    return "";
184  case EF_MIPS_MACH_3900:
185    return "r3900";
186  case EF_MIPS_MACH_4010:
187    return "r4010";
188  case EF_MIPS_MACH_4100:
189    return "r4100";
190  case EF_MIPS_MACH_4650:
191    return "r4650";
192  case EF_MIPS_MACH_4120:
193    return "r4120";
194  case EF_MIPS_MACH_4111:
195    return "r4111";
196  case EF_MIPS_MACH_5400:
197    return "vr5400";
198  case EF_MIPS_MACH_5900:
199    return "vr5900";
200  case EF_MIPS_MACH_5500:
201    return "vr5500";
202  case EF_MIPS_MACH_9000:
203    return "rm9000";
204  case EF_MIPS_MACH_LS2E:
205    return "loongson2e";
206  case EF_MIPS_MACH_LS2F:
207    return "loongson2f";
208  case EF_MIPS_MACH_LS3A:
209    return "loongson3a";
210  case EF_MIPS_MACH_OCTEON:
211    return "octeon";
212  case EF_MIPS_MACH_OCTEON2:
213    return "octeon2";
214  case EF_MIPS_MACH_OCTEON3:
215    return "octeon3";
216  case EF_MIPS_MACH_SB1:
217    return "sb1";
218  case EF_MIPS_MACH_XLR:
219    return "xlr";
220  default:
221    return "unknown machine";
222  }
223}
224
225static StringRef getArchName(uint32_t Flags) {
226  switch (Flags & EF_MIPS_ARCH) {
227  case EF_MIPS_ARCH_1:
228    return "mips1";
229  case EF_MIPS_ARCH_2:
230    return "mips2";
231  case EF_MIPS_ARCH_3:
232    return "mips3";
233  case EF_MIPS_ARCH_4:
234    return "mips4";
235  case EF_MIPS_ARCH_5:
236    return "mips5";
237  case EF_MIPS_ARCH_32:
238    return "mips32";
239  case EF_MIPS_ARCH_64:
240    return "mips64";
241  case EF_MIPS_ARCH_32R2:
242    return "mips32r2";
243  case EF_MIPS_ARCH_64R2:
244    return "mips64r2";
245  case EF_MIPS_ARCH_32R6:
246    return "mips32r6";
247  case EF_MIPS_ARCH_64R6:
248    return "mips64r6";
249  default:
250    return "unknown arch";
251  }
252}
253
254static std::string getFullArchName(uint32_t Flags) {
255  StringRef Arch = getArchName(Flags);
256  StringRef Mach = getMachName(Flags);
257  if (Mach.empty())
258    return Arch.str();
259  return (Arch + " (" + Mach + ")").str();
260}
261
262// There are (arguably too) many MIPS ISAs out there. Their relationships
263// can be represented as a forest. If all input files have ISAs which
264// reachable by repeated proceeding from the single child to the parent,
265// these input files are compatible. In that case we need to return "highest"
266// ISA. If there are incompatible input files, we show an error.
267// For example, mips1 is a "parent" of mips2 and such files are compatible.
268// Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
269// are incompatible because nor mips3 is a parent for misp32, nor mips32
270// is a parent for mips3.
271static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
272  uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
273
274  for (const FileFlags &F : Files.slice(1)) {
275    uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
276
277    // Check ISA compatibility.
278    if (isArchMatched(New, Ret))
279      continue;
280    if (!isArchMatched(Ret, New)) {
281      error("incompatible target ISA:\n>>> " + toString(Files[0].File) + ": " +
282            getFullArchName(Ret) + "\n>>> " + toString(F.File) + ": " +
283            getFullArchName(New));
284      return 0;
285    }
286    Ret = New;
287  }
288  return Ret;
289}
290
291template <class ELFT> uint32_t elf::calcMipsEFlags() {
292  std::vector<FileFlags> V;
293  for (InputFile *F : ObjectFiles)
294    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
295  if (V.empty())
296    return 0;
297  checkFlags(V);
298  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
299}
300
301static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
302  if (FpA == FpB)
303    return 0;
304  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
305    return 1;
306  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
307      FpA == Mips::Val_GNU_MIPS_ABI_FP_64)
308    return 1;
309  if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
310    return -1;
311  if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
312      FpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
313      FpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
314    return 1;
315  return -1;
316}
317
318static StringRef getMipsFpAbiName(uint8_t FpAbi) {
319  switch (FpAbi) {
320  case Mips::Val_GNU_MIPS_ABI_FP_ANY:
321    return "any";
322  case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
323    return "-mdouble-float";
324  case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
325    return "-msingle-float";
326  case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
327    return "-msoft-float";
328  case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
329    return "-mips32r2 -mfp64 (old)";
330  case Mips::Val_GNU_MIPS_ABI_FP_XX:
331    return "-mfpxx";
332  case Mips::Val_GNU_MIPS_ABI_FP_64:
333    return "-mgp32 -mfp64";
334  case Mips::Val_GNU_MIPS_ABI_FP_64A:
335    return "-mgp32 -mfp64 -mno-odd-spreg";
336  default:
337    return "unknown";
338  }
339}
340
341uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
342                              StringRef FileName) {
343  if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
344    return NewFlag;
345  if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
346    error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
347          "' is incompatible with '" + getMipsFpAbiName(NewFlag) +
348          "': " + FileName);
349  return OldFlag;
350}
351
352template <class ELFT> static bool isN32Abi(const InputFile *F) {
353  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
354    return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
355  return false;
356}
357
358bool elf::isMipsN32Abi(const InputFile *F) {
359  switch (Config->EKind) {
360  case ELF32LEKind:
361    return isN32Abi<ELF32LE>(F);
362  case ELF32BEKind:
363    return isN32Abi<ELF32BE>(F);
364  case ELF64LEKind:
365    return isN32Abi<ELF64LE>(F);
366  case ELF64BEKind:
367    return isN32Abi<ELF64BE>(F);
368  default:
369    llvm_unreachable("unknown Config->EKind");
370  }
371}
372
373bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; }
374
375bool elf::isMipsR6() {
376  uint32_t Arch = Config->EFlags & EF_MIPS_ARCH;
377  return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;
378}
379
380template uint32_t elf::calcMipsEFlags<ELF32LE>();
381template uint32_t elf::calcMipsEFlags<ELF32BE>();
382template uint32_t elf::calcMipsEFlags<ELF64LE>();
383template uint32_t elf::calcMipsEFlags<ELF64BE>();
384