xref: /openbsd-src/gnu/llvm/lld/ELF/Arch/MipsArchTree.cpp (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
1ece8a530Spatrick //===- MipsArchTree.cpp --------------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===---------------------------------------------------------------------===//
8ece8a530Spatrick //
9ece8a530Spatrick // This file contains a helper function for the Writer.
10ece8a530Spatrick //
11ece8a530Spatrick //===---------------------------------------------------------------------===//
12ece8a530Spatrick 
13ece8a530Spatrick #include "InputFiles.h"
14ece8a530Spatrick #include "SymbolTable.h"
15ece8a530Spatrick #include "Writer.h"
16ece8a530Spatrick 
17ece8a530Spatrick #include "lld/Common/ErrorHandler.h"
18ece8a530Spatrick #include "llvm/BinaryFormat/ELF.h"
19ece8a530Spatrick #include "llvm/Support/MipsABIFlags.h"
20ece8a530Spatrick 
21ece8a530Spatrick using namespace llvm;
22ece8a530Spatrick using namespace llvm::object;
23ece8a530Spatrick using namespace llvm::ELF;
24ece8a530Spatrick 
25bb684c34Spatrick using namespace lld;
26bb684c34Spatrick using namespace lld::elf;
27ece8a530Spatrick 
28ece8a530Spatrick namespace {
29ece8a530Spatrick struct ArchTreeEdge {
30ece8a530Spatrick   uint32_t child;
31ece8a530Spatrick   uint32_t parent;
32ece8a530Spatrick };
33ece8a530Spatrick 
34ece8a530Spatrick struct FileFlags {
35ece8a530Spatrick   InputFile *file;
36ece8a530Spatrick   uint32_t flags;
37ece8a530Spatrick };
38ece8a530Spatrick } // namespace
39ece8a530Spatrick 
getAbiName(uint32_t flags)40ece8a530Spatrick static StringRef getAbiName(uint32_t flags) {
41ece8a530Spatrick   switch (flags) {
42ece8a530Spatrick   case 0:
43ece8a530Spatrick     return "n64";
44ece8a530Spatrick   case EF_MIPS_ABI2:
45ece8a530Spatrick     return "n32";
46ece8a530Spatrick   case EF_MIPS_ABI_O32:
47ece8a530Spatrick     return "o32";
48ece8a530Spatrick   case EF_MIPS_ABI_O64:
49ece8a530Spatrick     return "o64";
50ece8a530Spatrick   case EF_MIPS_ABI_EABI32:
51ece8a530Spatrick     return "eabi32";
52ece8a530Spatrick   case EF_MIPS_ABI_EABI64:
53ece8a530Spatrick     return "eabi64";
54ece8a530Spatrick   default:
55ece8a530Spatrick     return "unknown";
56ece8a530Spatrick   }
57ece8a530Spatrick }
58ece8a530Spatrick 
getNanName(bool isNan2008)59ece8a530Spatrick static StringRef getNanName(bool isNan2008) {
60ece8a530Spatrick   return isNan2008 ? "2008" : "legacy";
61ece8a530Spatrick }
62ece8a530Spatrick 
getFpName(bool isFp64)63ece8a530Spatrick static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
64ece8a530Spatrick 
checkFlags(ArrayRef<FileFlags> files)65ece8a530Spatrick static void checkFlags(ArrayRef<FileFlags> files) {
66ece8a530Spatrick   assert(!files.empty() && "expected non-empty file list");
67ece8a530Spatrick 
68ece8a530Spatrick   uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
69ece8a530Spatrick   bool nan = files[0].flags & EF_MIPS_NAN2008;
70ece8a530Spatrick   bool fp = files[0].flags & EF_MIPS_FP64;
71ece8a530Spatrick 
72ece8a530Spatrick   for (const FileFlags &f : files) {
73ece8a530Spatrick     if (config->is64 && f.flags & EF_MIPS_MICROMIPS)
74ece8a530Spatrick       error(toString(f.file) + ": microMIPS 64-bit is not supported");
75ece8a530Spatrick 
76ece8a530Spatrick     uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
77ece8a530Spatrick     if (abi != abi2)
78ece8a530Spatrick       error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
79ece8a530Spatrick             "' is incompatible with target ABI '" + getAbiName(abi) + "'");
80ece8a530Spatrick 
81ece8a530Spatrick     bool nan2 = f.flags & EF_MIPS_NAN2008;
82ece8a530Spatrick     if (nan != nan2)
83ece8a530Spatrick       error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
84ece8a530Spatrick             " is incompatible with target -mnan=" + getNanName(nan));
85ece8a530Spatrick 
86ece8a530Spatrick     bool fp2 = f.flags & EF_MIPS_FP64;
87ece8a530Spatrick     if (fp != fp2)
88ece8a530Spatrick       error(toString(f.file) + ": -mfp" + getFpName(fp2) +
89ece8a530Spatrick             " is incompatible with target -mfp" + getFpName(fp));
90ece8a530Spatrick   }
91ece8a530Spatrick }
92ece8a530Spatrick 
getMiscFlags(ArrayRef<FileFlags> files)93ece8a530Spatrick static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
94ece8a530Spatrick   uint32_t ret = 0;
95ece8a530Spatrick   for (const FileFlags &f : files)
96ece8a530Spatrick     ret |= f.flags &
97ece8a530Spatrick            (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
98ece8a530Spatrick             EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
99ece8a530Spatrick   return ret;
100ece8a530Spatrick }
101ece8a530Spatrick 
getPicFlags(ArrayRef<FileFlags> files)102ece8a530Spatrick static uint32_t getPicFlags(ArrayRef<FileFlags> files) {
103ece8a530Spatrick   // Check PIC/non-PIC compatibility.
104ece8a530Spatrick   bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
105ece8a530Spatrick   for (const FileFlags &f : files.slice(1)) {
106ece8a530Spatrick     bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
107ece8a530Spatrick     if (isPic && !isPic2)
108ece8a530Spatrick       warn(toString(f.file) +
109ece8a530Spatrick            ": linking non-abicalls code with abicalls code " +
110ece8a530Spatrick            toString(files[0].file));
111ece8a530Spatrick     if (!isPic && isPic2)
112ece8a530Spatrick       warn(toString(f.file) +
113ece8a530Spatrick            ": linking abicalls code with non-abicalls code " +
114ece8a530Spatrick            toString(files[0].file));
115ece8a530Spatrick   }
116ece8a530Spatrick 
117ece8a530Spatrick   // Compute the result PIC/non-PIC flag.
118ece8a530Spatrick   uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
119ece8a530Spatrick   for (const FileFlags &f : files.slice(1))
120ece8a530Spatrick     ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
121ece8a530Spatrick 
122ece8a530Spatrick   // PIC code is inherently CPIC and may not set CPIC flag explicitly.
123ece8a530Spatrick   if (ret & EF_MIPS_PIC)
124ece8a530Spatrick     ret |= EF_MIPS_CPIC;
125ece8a530Spatrick   return ret;
126ece8a530Spatrick }
127ece8a530Spatrick 
128ece8a530Spatrick static ArchTreeEdge archTree[] = {
129ece8a530Spatrick     // MIPS32R6 and MIPS64R6 are not compatible with other extensions
130ece8a530Spatrick     // MIPS64R2 extensions.
131ece8a530Spatrick     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
132ece8a530Spatrick     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
133ece8a530Spatrick     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
134ece8a530Spatrick     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
135ece8a530Spatrick     // MIPS64 extensions.
136ece8a530Spatrick     {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
137ece8a530Spatrick     {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
138ece8a530Spatrick     {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
139ece8a530Spatrick     // MIPS V extensions.
140ece8a530Spatrick     {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
141ece8a530Spatrick     // R5000 extensions.
142ece8a530Spatrick     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
143ece8a530Spatrick     // MIPS IV extensions.
144ece8a530Spatrick     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
145ece8a530Spatrick     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
146ece8a530Spatrick     {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
147ece8a530Spatrick     // VR4100 extensions.
148ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
149ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
150ece8a530Spatrick     // MIPS III extensions.
151ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
152ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
153ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
154ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
155ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
156ece8a530Spatrick     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
157ece8a530Spatrick     {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
158ece8a530Spatrick     // MIPS32 extensions.
159ece8a530Spatrick     {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
160ece8a530Spatrick     // MIPS II extensions.
161ece8a530Spatrick     {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
162ece8a530Spatrick     {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
163ece8a530Spatrick     // MIPS I extensions.
164ece8a530Spatrick     {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
165ece8a530Spatrick     {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
166ece8a530Spatrick };
167ece8a530Spatrick 
isArchMatched(uint32_t newFlags,uint32_t res)168ece8a530Spatrick static bool isArchMatched(uint32_t newFlags, uint32_t res) {
169ece8a530Spatrick   if (newFlags == res)
170ece8a530Spatrick     return true;
171ece8a530Spatrick   if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
172ece8a530Spatrick     return true;
173ece8a530Spatrick   if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
174ece8a530Spatrick     return true;
175ece8a530Spatrick   for (const auto &edge : archTree) {
176ece8a530Spatrick     if (res == edge.child) {
177ece8a530Spatrick       res = edge.parent;
178ece8a530Spatrick       if (res == newFlags)
179ece8a530Spatrick         return true;
180ece8a530Spatrick     }
181ece8a530Spatrick   }
182ece8a530Spatrick   return false;
183ece8a530Spatrick }
184ece8a530Spatrick 
getMachName(uint32_t flags)185ece8a530Spatrick static StringRef getMachName(uint32_t flags) {
186ece8a530Spatrick   switch (flags & EF_MIPS_MACH) {
187ece8a530Spatrick   case EF_MIPS_MACH_NONE:
188ece8a530Spatrick     return "";
189ece8a530Spatrick   case EF_MIPS_MACH_3900:
190ece8a530Spatrick     return "r3900";
191ece8a530Spatrick   case EF_MIPS_MACH_4010:
192ece8a530Spatrick     return "r4010";
193ece8a530Spatrick   case EF_MIPS_MACH_4100:
194ece8a530Spatrick     return "r4100";
195ece8a530Spatrick   case EF_MIPS_MACH_4650:
196ece8a530Spatrick     return "r4650";
197ece8a530Spatrick   case EF_MIPS_MACH_4120:
198ece8a530Spatrick     return "r4120";
199ece8a530Spatrick   case EF_MIPS_MACH_4111:
200ece8a530Spatrick     return "r4111";
201ece8a530Spatrick   case EF_MIPS_MACH_5400:
202ece8a530Spatrick     return "vr5400";
203ece8a530Spatrick   case EF_MIPS_MACH_5900:
204ece8a530Spatrick     return "vr5900";
205ece8a530Spatrick   case EF_MIPS_MACH_5500:
206ece8a530Spatrick     return "vr5500";
207ece8a530Spatrick   case EF_MIPS_MACH_9000:
208ece8a530Spatrick     return "rm9000";
209ece8a530Spatrick   case EF_MIPS_MACH_LS2E:
210ece8a530Spatrick     return "loongson2e";
211ece8a530Spatrick   case EF_MIPS_MACH_LS2F:
212ece8a530Spatrick     return "loongson2f";
213ece8a530Spatrick   case EF_MIPS_MACH_LS3A:
214ece8a530Spatrick     return "loongson3a";
215ece8a530Spatrick   case EF_MIPS_MACH_OCTEON:
216ece8a530Spatrick     return "octeon";
217ece8a530Spatrick   case EF_MIPS_MACH_OCTEON2:
218ece8a530Spatrick     return "octeon2";
219ece8a530Spatrick   case EF_MIPS_MACH_OCTEON3:
220ece8a530Spatrick     return "octeon3";
221ece8a530Spatrick   case EF_MIPS_MACH_SB1:
222ece8a530Spatrick     return "sb1";
223ece8a530Spatrick   case EF_MIPS_MACH_XLR:
224ece8a530Spatrick     return "xlr";
225ece8a530Spatrick   default:
226ece8a530Spatrick     return "unknown machine";
227ece8a530Spatrick   }
228ece8a530Spatrick }
229ece8a530Spatrick 
getArchName(uint32_t flags)230ece8a530Spatrick static StringRef getArchName(uint32_t flags) {
231ece8a530Spatrick   switch (flags & EF_MIPS_ARCH) {
232ece8a530Spatrick   case EF_MIPS_ARCH_1:
233ece8a530Spatrick     return "mips1";
234ece8a530Spatrick   case EF_MIPS_ARCH_2:
235ece8a530Spatrick     return "mips2";
236ece8a530Spatrick   case EF_MIPS_ARCH_3:
237ece8a530Spatrick     return "mips3";
238ece8a530Spatrick   case EF_MIPS_ARCH_4:
239ece8a530Spatrick     return "mips4";
240ece8a530Spatrick   case EF_MIPS_ARCH_5:
241ece8a530Spatrick     return "mips5";
242ece8a530Spatrick   case EF_MIPS_ARCH_32:
243ece8a530Spatrick     return "mips32";
244ece8a530Spatrick   case EF_MIPS_ARCH_64:
245ece8a530Spatrick     return "mips64";
246ece8a530Spatrick   case EF_MIPS_ARCH_32R2:
247ece8a530Spatrick     return "mips32r2";
248ece8a530Spatrick   case EF_MIPS_ARCH_64R2:
249ece8a530Spatrick     return "mips64r2";
250ece8a530Spatrick   case EF_MIPS_ARCH_32R6:
251ece8a530Spatrick     return "mips32r6";
252ece8a530Spatrick   case EF_MIPS_ARCH_64R6:
253ece8a530Spatrick     return "mips64r6";
254ece8a530Spatrick   default:
255ece8a530Spatrick     return "unknown arch";
256ece8a530Spatrick   }
257ece8a530Spatrick }
258ece8a530Spatrick 
getFullArchName(uint32_t flags)259ece8a530Spatrick static std::string getFullArchName(uint32_t flags) {
260ece8a530Spatrick   StringRef arch = getArchName(flags);
261ece8a530Spatrick   StringRef mach = getMachName(flags);
262ece8a530Spatrick   if (mach.empty())
263ece8a530Spatrick     return arch.str();
264ece8a530Spatrick   return (arch + " (" + mach + ")").str();
265ece8a530Spatrick }
266ece8a530Spatrick 
267ece8a530Spatrick // There are (arguably too) many MIPS ISAs out there. Their relationships
268ece8a530Spatrick // can be represented as a forest. If all input files have ISAs which
269ece8a530Spatrick // reachable by repeated proceeding from the single child to the parent,
270ece8a530Spatrick // these input files are compatible. In that case we need to return "highest"
271ece8a530Spatrick // ISA. If there are incompatible input files, we show an error.
272ece8a530Spatrick // For example, mips1 is a "parent" of mips2 and such files are compatible.
273ece8a530Spatrick // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
274ece8a530Spatrick // are incompatible because nor mips3 is a parent for misp32, nor mips32
275ece8a530Spatrick // is a parent for mips3.
getArchFlags(ArrayRef<FileFlags> files)276ece8a530Spatrick static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
277ece8a530Spatrick   uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
278ece8a530Spatrick 
279ece8a530Spatrick   for (const FileFlags &f : files.slice(1)) {
280ece8a530Spatrick     uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
281ece8a530Spatrick 
282ece8a530Spatrick     // Check ISA compatibility.
283ece8a530Spatrick     if (isArchMatched(newFlags, ret))
284ece8a530Spatrick       continue;
285ece8a530Spatrick     if (!isArchMatched(ret, newFlags)) {
286ece8a530Spatrick       error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
287ece8a530Spatrick             getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
288ece8a530Spatrick             getFullArchName(newFlags));
289ece8a530Spatrick       return 0;
290ece8a530Spatrick     }
291ece8a530Spatrick     ret = newFlags;
292ece8a530Spatrick   }
293ece8a530Spatrick   return ret;
294ece8a530Spatrick }
295ece8a530Spatrick 
calcMipsEFlags()296bb684c34Spatrick template <class ELFT> uint32_t elf::calcMipsEFlags() {
297ece8a530Spatrick   std::vector<FileFlags> v;
298*dfe94b16Srobert   for (InputFile *f : ctx.objectFiles)
2991cf9926bSpatrick     v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags});
300ece8a530Spatrick   if (v.empty()) {
301ece8a530Spatrick     // If we don't have any input files, we'll have to rely on the information
302ece8a530Spatrick     // we can derive from emulation information, since this at least gets us
303ece8a530Spatrick     // ABI.
304ece8a530Spatrick     if (config->emulation.empty() || config->is64)
305ece8a530Spatrick       return 0;
306ece8a530Spatrick     return config->mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
307ece8a530Spatrick   }
308ece8a530Spatrick   checkFlags(v);
309ece8a530Spatrick   return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
310ece8a530Spatrick }
311ece8a530Spatrick 
compareMipsFpAbi(uint8_t fpA,uint8_t fpB)312ece8a530Spatrick static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
313ece8a530Spatrick   if (fpA == fpB)
314ece8a530Spatrick     return 0;
315ece8a530Spatrick   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
316ece8a530Spatrick     return 1;
317ece8a530Spatrick   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
318ece8a530Spatrick       fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
319ece8a530Spatrick     return 1;
320ece8a530Spatrick   if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
321ece8a530Spatrick     return -1;
322ece8a530Spatrick   if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
323ece8a530Spatrick       fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
324ece8a530Spatrick       fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
325ece8a530Spatrick     return 1;
326ece8a530Spatrick   return -1;
327ece8a530Spatrick }
328ece8a530Spatrick 
getMipsFpAbiName(uint8_t fpAbi)329ece8a530Spatrick static StringRef getMipsFpAbiName(uint8_t fpAbi) {
330ece8a530Spatrick   switch (fpAbi) {
331ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_ANY:
332ece8a530Spatrick     return "any";
333ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
334ece8a530Spatrick     return "-mdouble-float";
335ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
336ece8a530Spatrick     return "-msingle-float";
337ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
338ece8a530Spatrick     return "-msoft-float";
339ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
340ece8a530Spatrick     return "-mgp32 -mfp64 (old)";
341ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_XX:
342ece8a530Spatrick     return "-mfpxx";
343ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_64:
344ece8a530Spatrick     return "-mgp32 -mfp64";
345ece8a530Spatrick   case Mips::Val_GNU_MIPS_ABI_FP_64A:
346ece8a530Spatrick     return "-mgp32 -mfp64 -mno-odd-spreg";
347ece8a530Spatrick   default:
348ece8a530Spatrick     return "unknown";
349ece8a530Spatrick   }
350ece8a530Spatrick }
351ece8a530Spatrick 
getMipsFpAbiFlag(uint8_t oldFlag,uint8_t newFlag,StringRef fileName)352bb684c34Spatrick uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
353bb684c34Spatrick                               StringRef fileName) {
354ece8a530Spatrick   if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
355ece8a530Spatrick     return newFlag;
356ece8a530Spatrick   if (compareMipsFpAbi(oldFlag, newFlag) < 0)
357ece8a530Spatrick     error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
358ece8a530Spatrick           "' is incompatible with target floating point ABI '" +
359ece8a530Spatrick           getMipsFpAbiName(oldFlag) + "'");
360ece8a530Spatrick   return oldFlag;
361ece8a530Spatrick }
362ece8a530Spatrick 
isN32Abi(const InputFile * f)363ece8a530Spatrick template <class ELFT> static bool isN32Abi(const InputFile *f) {
364ece8a530Spatrick   if (auto *ef = dyn_cast<ELFFileBase>(f))
3651cf9926bSpatrick     return ef->template getObj<ELFT>().getHeader().e_flags & EF_MIPS_ABI2;
366ece8a530Spatrick   return false;
367ece8a530Spatrick }
368ece8a530Spatrick 
isMipsN32Abi(const InputFile * f)369bb684c34Spatrick bool elf::isMipsN32Abi(const InputFile *f) {
370ece8a530Spatrick   switch (config->ekind) {
371ece8a530Spatrick   case ELF32LEKind:
372ece8a530Spatrick     return isN32Abi<ELF32LE>(f);
373ece8a530Spatrick   case ELF32BEKind:
374ece8a530Spatrick     return isN32Abi<ELF32BE>(f);
375ece8a530Spatrick   case ELF64LEKind:
376ece8a530Spatrick     return isN32Abi<ELF64LE>(f);
377ece8a530Spatrick   case ELF64BEKind:
378ece8a530Spatrick     return isN32Abi<ELF64BE>(f);
379ece8a530Spatrick   default:
380ece8a530Spatrick     llvm_unreachable("unknown Config->EKind");
381ece8a530Spatrick   }
382ece8a530Spatrick }
383ece8a530Spatrick 
isMicroMips()384bb684c34Spatrick bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
385ece8a530Spatrick 
isMipsR6()386bb684c34Spatrick bool elf::isMipsR6() {
387ece8a530Spatrick   uint32_t arch = config->eflags & EF_MIPS_ARCH;
388ece8a530Spatrick   return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
389ece8a530Spatrick }
390ece8a530Spatrick 
391bb684c34Spatrick template uint32_t elf::calcMipsEFlags<ELF32LE>();
392bb684c34Spatrick template uint32_t elf::calcMipsEFlags<ELF32BE>();
393bb684c34Spatrick template uint32_t elf::calcMipsEFlags<ELF64LE>();
394bb684c34Spatrick template uint32_t elf::calcMipsEFlags<ELF64BE>();
395