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