xref: /llvm-project/lld/ELF/Arch/MipsArchTree.cpp (revision c4dc5ed8254e6b318200496d687b0a7b3163dc26)
1f3e3629fSKonstantin Zhuravlyov //===- MipsArchTree.cpp --------------------------------------------------===//
2f3e3629fSKonstantin Zhuravlyov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f3e3629fSKonstantin Zhuravlyov //
7f3e3629fSKonstantin Zhuravlyov //===---------------------------------------------------------------------===//
8f3e3629fSKonstantin Zhuravlyov //
9f3e3629fSKonstantin Zhuravlyov // This file contains a helper function for the Writer.
10f3e3629fSKonstantin Zhuravlyov //
11f3e3629fSKonstantin Zhuravlyov //===---------------------------------------------------------------------===//
12f3e3629fSKonstantin Zhuravlyov 
1338fbedabSFangrui Song #include "InputFiles.h"
14f3e3629fSKonstantin Zhuravlyov #include "SymbolTable.h"
15b3e0bd3dSFangrui Song #include "Target.h"
16f3e3629fSKonstantin Zhuravlyov #include "Writer.h"
17f3e3629fSKonstantin Zhuravlyov 
18b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h"
19f3e3629fSKonstantin Zhuravlyov #include "llvm/BinaryFormat/ELF.h"
20f3e3629fSKonstantin Zhuravlyov #include "llvm/Support/MipsABIFlags.h"
21f3e3629fSKonstantin Zhuravlyov 
22f3e3629fSKonstantin Zhuravlyov using namespace llvm;
23f3e3629fSKonstantin Zhuravlyov using namespace llvm::object;
24f3e3629fSKonstantin Zhuravlyov using namespace llvm::ELF;
25f3e3629fSKonstantin Zhuravlyov 
2607837b8fSFangrui Song using namespace lld;
2707837b8fSFangrui Song using namespace lld::elf;
28f3e3629fSKonstantin Zhuravlyov 
29f3e3629fSKonstantin Zhuravlyov namespace {
30f3e3629fSKonstantin Zhuravlyov struct ArchTreeEdge {
313837f427SRui Ueyama   uint32_t child;
323837f427SRui Ueyama   uint32_t parent;
33f3e3629fSKonstantin Zhuravlyov };
34f3e3629fSKonstantin Zhuravlyov 
35f3e3629fSKonstantin Zhuravlyov struct FileFlags {
363837f427SRui Ueyama   InputFile *file;
373837f427SRui Ueyama   uint32_t flags;
38f3e3629fSKonstantin Zhuravlyov };
3967c60727SGeorge Rimar } // namespace
40f3e3629fSKonstantin Zhuravlyov 
413837f427SRui Ueyama static StringRef getAbiName(uint32_t flags) {
423837f427SRui Ueyama   switch (flags) {
43f3e3629fSKonstantin Zhuravlyov   case 0:
44f3e3629fSKonstantin Zhuravlyov     return "n64";
45f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ABI2:
46f3e3629fSKonstantin Zhuravlyov     return "n32";
47f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ABI_O32:
48f3e3629fSKonstantin Zhuravlyov     return "o32";
49f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ABI_O64:
50f3e3629fSKonstantin Zhuravlyov     return "o64";
51f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ABI_EABI32:
52f3e3629fSKonstantin Zhuravlyov     return "eabi32";
53f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ABI_EABI64:
54f3e3629fSKonstantin Zhuravlyov     return "eabi64";
55f3e3629fSKonstantin Zhuravlyov   default:
56f3e3629fSKonstantin Zhuravlyov     return "unknown";
57f3e3629fSKonstantin Zhuravlyov   }
58f3e3629fSKonstantin Zhuravlyov }
59f3e3629fSKonstantin Zhuravlyov 
603837f427SRui Ueyama static StringRef getNanName(bool isNan2008) {
613837f427SRui Ueyama   return isNan2008 ? "2008" : "legacy";
62f3e3629fSKonstantin Zhuravlyov }
63f3e3629fSKonstantin Zhuravlyov 
643837f427SRui Ueyama static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
65f3e3629fSKonstantin Zhuravlyov 
666d03a690SFangrui Song static void checkFlags(Ctx &ctx, ArrayRef<FileFlags> files) {
673837f427SRui Ueyama   assert(!files.empty() && "expected non-empty file list");
6878c46bdfSSimon Atanasyan 
693837f427SRui Ueyama   uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
703837f427SRui Ueyama   bool nan = files[0].flags & EF_MIPS_NAN2008;
713837f427SRui Ueyama   bool fp = files[0].flags & EF_MIPS_FP64;
72f3e3629fSKonstantin Zhuravlyov 
733837f427SRui Ueyama   for (const FileFlags &f : files) {
741dd9a565SFangrui Song     if (ctx.arg.is64 && f.flags & EF_MIPS_MICROMIPS)
75*c4dc5ed8SFangrui Song       Err(ctx) << f.file << ": microMIPS 64-bit is not supported";
760905b953SSimon Atanasyan 
773837f427SRui Ueyama     uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
783837f427SRui Ueyama     if (abi != abi2)
79*c4dc5ed8SFangrui Song       Err(ctx) << f.file << ": ABI '" << getAbiName(abi2)
8009c2c5e1SFangrui Song                << "' is incompatible with target ABI '" << getAbiName(abi)
8109c2c5e1SFangrui Song                << "'";
82f3e3629fSKonstantin Zhuravlyov 
833837f427SRui Ueyama     bool nan2 = f.flags & EF_MIPS_NAN2008;
843837f427SRui Ueyama     if (nan != nan2)
85*c4dc5ed8SFangrui Song       Err(ctx) << f.file << ": -mnan=" << getNanName(nan2)
86*c4dc5ed8SFangrui Song                << " is incompatible with target -mnan=" << getNanName(nan);
87f3e3629fSKonstantin Zhuravlyov 
883837f427SRui Ueyama     bool fp2 = f.flags & EF_MIPS_FP64;
893837f427SRui Ueyama     if (fp != fp2)
90*c4dc5ed8SFangrui Song       Err(ctx) << f.file << ": -mfp" << getFpName(fp2)
9109c2c5e1SFangrui Song                << " is incompatible with target -mfp" << getFpName(fp);
92f3e3629fSKonstantin Zhuravlyov   }
93f3e3629fSKonstantin Zhuravlyov }
94f3e3629fSKonstantin Zhuravlyov 
953837f427SRui Ueyama static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
963837f427SRui Ueyama   uint32_t ret = 0;
973837f427SRui Ueyama   for (const FileFlags &f : files)
983837f427SRui Ueyama     ret |= f.flags &
99f3e3629fSKonstantin Zhuravlyov            (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
100f3e3629fSKonstantin Zhuravlyov             EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
1013837f427SRui Ueyama   return ret;
102f3e3629fSKonstantin Zhuravlyov }
103f3e3629fSKonstantin Zhuravlyov 
104e24457a3SFangrui Song static uint32_t getPicFlags(Ctx &ctx, ArrayRef<FileFlags> files) {
105f3e3629fSKonstantin Zhuravlyov   // Check PIC/non-PIC compatibility.
1063837f427SRui Ueyama   bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
1073837f427SRui Ueyama   for (const FileFlags &f : files.slice(1)) {
1083837f427SRui Ueyama     bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
1093837f427SRui Ueyama     if (isPic && !isPic2)
110f8bae3afSFangrui Song       Warn(ctx) << f.file << ": linking non-abicalls code with abicalls code "
111f8bae3afSFangrui Song                 << files[0].file;
1123837f427SRui Ueyama     if (!isPic && isPic2)
113f8bae3afSFangrui Song       Warn(ctx) << f.file << ": linking abicalls code with non-abicalls code "
114f8bae3afSFangrui Song                 << files[0].file;
115f3e3629fSKonstantin Zhuravlyov   }
116f3e3629fSKonstantin Zhuravlyov 
117f3e3629fSKonstantin Zhuravlyov   // Compute the result PIC/non-PIC flag.
1183837f427SRui Ueyama   uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
1193837f427SRui Ueyama   for (const FileFlags &f : files.slice(1))
1203837f427SRui Ueyama     ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
121f3e3629fSKonstantin Zhuravlyov 
122f3e3629fSKonstantin Zhuravlyov   // PIC code is inherently CPIC and may not set CPIC flag explicitly.
1233837f427SRui Ueyama   if (ret & EF_MIPS_PIC)
1243837f427SRui Ueyama     ret |= EF_MIPS_CPIC;
1253837f427SRui Ueyama   return ret;
126f3e3629fSKonstantin Zhuravlyov }
127f3e3629fSKonstantin Zhuravlyov 
1283837f427SRui Ueyama static ArchTreeEdge archTree[] = {
129f3e3629fSKonstantin Zhuravlyov     // MIPS32R6 and MIPS64R6 are not compatible with other extensions
130f3e3629fSKonstantin Zhuravlyov     // MIPS64R2 extensions.
131f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
132f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, EF_MIPS_ARCH_64R2},
133f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, EF_MIPS_ARCH_64R2},
134f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, EF_MIPS_ARCH_64R2},
135f3e3629fSKonstantin Zhuravlyov     // MIPS64 extensions.
136f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, EF_MIPS_ARCH_64},
137f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, EF_MIPS_ARCH_64},
138f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
139f3e3629fSKonstantin Zhuravlyov     // MIPS V extensions.
140f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
141f3e3629fSKonstantin Zhuravlyov     // R5000 extensions.
142f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400},
143f3e3629fSKonstantin Zhuravlyov     // MIPS IV extensions.
144f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, EF_MIPS_ARCH_4},
145f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, EF_MIPS_ARCH_4},
146f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
147f3e3629fSKonstantin Zhuravlyov     // VR4100 extensions.
148f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
149f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100},
150f3e3629fSKonstantin Zhuravlyov     // MIPS III extensions.
151f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, EF_MIPS_ARCH_3},
152f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, EF_MIPS_ARCH_3},
153f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, EF_MIPS_ARCH_3},
154f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, EF_MIPS_ARCH_3},
155f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, EF_MIPS_ARCH_3},
156f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, EF_MIPS_ARCH_3},
157f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
158f3e3629fSKonstantin Zhuravlyov     // MIPS32 extensions.
159f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
160f3e3629fSKonstantin Zhuravlyov     // MIPS II extensions.
161f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
162f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
163f3e3629fSKonstantin Zhuravlyov     // MIPS I extensions.
164f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, EF_MIPS_ARCH_1},
165f3e3629fSKonstantin Zhuravlyov     {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
166f3e3629fSKonstantin Zhuravlyov };
167f3e3629fSKonstantin Zhuravlyov 
168ab04ad6aSFangrui Song static bool isArchMatched(uint32_t newFlags, uint32_t res) {
169ab04ad6aSFangrui Song   if (newFlags == res)
170f3e3629fSKonstantin Zhuravlyov     return true;
171ab04ad6aSFangrui Song   if (newFlags == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
172f3e3629fSKonstantin Zhuravlyov     return true;
173ab04ad6aSFangrui Song   if (newFlags == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
174f3e3629fSKonstantin Zhuravlyov     return true;
1753837f427SRui Ueyama   for (const auto &edge : archTree) {
1763837f427SRui Ueyama     if (res == edge.child) {
1773837f427SRui Ueyama       res = edge.parent;
178ab04ad6aSFangrui Song       if (res == newFlags)
179f3e3629fSKonstantin Zhuravlyov         return true;
180f3e3629fSKonstantin Zhuravlyov     }
181f3e3629fSKonstantin Zhuravlyov   }
182f3e3629fSKonstantin Zhuravlyov   return false;
183f3e3629fSKonstantin Zhuravlyov }
184f3e3629fSKonstantin Zhuravlyov 
1853837f427SRui Ueyama static StringRef getMachName(uint32_t flags) {
1863837f427SRui Ueyama   switch (flags & EF_MIPS_MACH) {
187f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_NONE:
188f3e3629fSKonstantin Zhuravlyov     return "";
189f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_3900:
190f3e3629fSKonstantin Zhuravlyov     return "r3900";
191f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_4010:
192f3e3629fSKonstantin Zhuravlyov     return "r4010";
193f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_4100:
194f3e3629fSKonstantin Zhuravlyov     return "r4100";
195f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_4650:
196f3e3629fSKonstantin Zhuravlyov     return "r4650";
197f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_4120:
198f3e3629fSKonstantin Zhuravlyov     return "r4120";
199f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_4111:
200f3e3629fSKonstantin Zhuravlyov     return "r4111";
201f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_5400:
202f3e3629fSKonstantin Zhuravlyov     return "vr5400";
203f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_5900:
204f3e3629fSKonstantin Zhuravlyov     return "vr5900";
205f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_5500:
206f3e3629fSKonstantin Zhuravlyov     return "vr5500";
207f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_9000:
208f3e3629fSKonstantin Zhuravlyov     return "rm9000";
209f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_LS2E:
210f3e3629fSKonstantin Zhuravlyov     return "loongson2e";
211f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_LS2F:
212f3e3629fSKonstantin Zhuravlyov     return "loongson2f";
213f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_LS3A:
214f3e3629fSKonstantin Zhuravlyov     return "loongson3a";
215f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_OCTEON:
216f3e3629fSKonstantin Zhuravlyov     return "octeon";
217f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_OCTEON2:
218f3e3629fSKonstantin Zhuravlyov     return "octeon2";
219f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_OCTEON3:
220f3e3629fSKonstantin Zhuravlyov     return "octeon3";
221f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_SB1:
222f3e3629fSKonstantin Zhuravlyov     return "sb1";
223f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_MACH_XLR:
224f3e3629fSKonstantin Zhuravlyov     return "xlr";
225f3e3629fSKonstantin Zhuravlyov   default:
226f3e3629fSKonstantin Zhuravlyov     return "unknown machine";
227f3e3629fSKonstantin Zhuravlyov   }
228f3e3629fSKonstantin Zhuravlyov }
229f3e3629fSKonstantin Zhuravlyov 
2303837f427SRui Ueyama static StringRef getArchName(uint32_t flags) {
2313837f427SRui Ueyama   switch (flags & EF_MIPS_ARCH) {
232f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_1:
233f3e3629fSKonstantin Zhuravlyov     return "mips1";
234f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_2:
235f3e3629fSKonstantin Zhuravlyov     return "mips2";
236f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_3:
237f3e3629fSKonstantin Zhuravlyov     return "mips3";
238f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_4:
239f3e3629fSKonstantin Zhuravlyov     return "mips4";
240f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_5:
241f3e3629fSKonstantin Zhuravlyov     return "mips5";
242f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_32:
243f3e3629fSKonstantin Zhuravlyov     return "mips32";
244f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_64:
245f3e3629fSKonstantin Zhuravlyov     return "mips64";
246f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_32R2:
247f3e3629fSKonstantin Zhuravlyov     return "mips32r2";
248f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_64R2:
249f3e3629fSKonstantin Zhuravlyov     return "mips64r2";
250f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_32R6:
251f3e3629fSKonstantin Zhuravlyov     return "mips32r6";
252f3e3629fSKonstantin Zhuravlyov   case EF_MIPS_ARCH_64R6:
253f3e3629fSKonstantin Zhuravlyov     return "mips64r6";
254f3e3629fSKonstantin Zhuravlyov   default:
255f3e3629fSKonstantin Zhuravlyov     return "unknown arch";
256f3e3629fSKonstantin Zhuravlyov   }
257f3e3629fSKonstantin Zhuravlyov }
258f3e3629fSKonstantin Zhuravlyov 
2593837f427SRui Ueyama static std::string getFullArchName(uint32_t flags) {
2603837f427SRui Ueyama   StringRef arch = getArchName(flags);
2613837f427SRui Ueyama   StringRef mach = getMachName(flags);
2623837f427SRui Ueyama   if (mach.empty())
2633837f427SRui Ueyama     return arch.str();
2643837f427SRui Ueyama   return (arch + " (" + mach + ")").str();
265280252c6SAlexander Richardson }
266280252c6SAlexander Richardson 
267f3e3629fSKonstantin Zhuravlyov // There are (arguably too) many MIPS ISAs out there. Their relationships
268f3e3629fSKonstantin Zhuravlyov // can be represented as a forest. If all input files have ISAs which
269f3e3629fSKonstantin Zhuravlyov // reachable by repeated proceeding from the single child to the parent,
270f3e3629fSKonstantin Zhuravlyov // these input files are compatible. In that case we need to return "highest"
271f3e3629fSKonstantin Zhuravlyov // ISA. If there are incompatible input files, we show an error.
272f3e3629fSKonstantin Zhuravlyov // For example, mips1 is a "parent" of mips2 and such files are compatible.
273f3e3629fSKonstantin Zhuravlyov // Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
274f3e3629fSKonstantin Zhuravlyov // are incompatible because nor mips3 is a parent for misp32, nor mips32
275f3e3629fSKonstantin Zhuravlyov // is a parent for mips3.
276e24457a3SFangrui Song static uint32_t getArchFlags(Ctx &ctx, ArrayRef<FileFlags> files) {
2773837f427SRui Ueyama   uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
278f3e3629fSKonstantin Zhuravlyov 
2793837f427SRui Ueyama   for (const FileFlags &f : files.slice(1)) {
280ab04ad6aSFangrui Song     uint32_t newFlags = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
281f3e3629fSKonstantin Zhuravlyov 
282f3e3629fSKonstantin Zhuravlyov     // Check ISA compatibility.
283ab04ad6aSFangrui Song     if (isArchMatched(newFlags, ret))
284f3e3629fSKonstantin Zhuravlyov       continue;
285ab04ad6aSFangrui Song     if (!isArchMatched(ret, newFlags)) {
286*c4dc5ed8SFangrui Song       Err(ctx) << "incompatible target ISA:\n>>> " << files[0].file << ": "
287*c4dc5ed8SFangrui Song                << getFullArchName(ret) << "\n>>> " << f.file << ": "
288*c4dc5ed8SFangrui Song                << getFullArchName(newFlags);
289f3e3629fSKonstantin Zhuravlyov       return 0;
290f3e3629fSKonstantin Zhuravlyov     }
291ab04ad6aSFangrui Song     ret = newFlags;
292f3e3629fSKonstantin Zhuravlyov   }
2933837f427SRui Ueyama   return ret;
294f3e3629fSKonstantin Zhuravlyov }
295f3e3629fSKonstantin Zhuravlyov 
2966d03a690SFangrui Song template <class ELFT> uint32_t elf::calcMipsEFlags(Ctx &ctx) {
2973837f427SRui Ueyama   std::vector<FileFlags> v;
29834fa8600SFangrui Song   for (InputFile *f : ctx.objectFiles)
2994845531fSGeorgii Rymar     v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader().e_flags});
300355764e3SGeorge Rimar   if (v.empty()) {
301355764e3SGeorge Rimar     // If we don't have any input files, we'll have to rely on the information
302355764e3SGeorge Rimar     // we can derive from emulation information, since this at least gets us
303355764e3SGeorge Rimar     // ABI.
3041dd9a565SFangrui Song     if (ctx.arg.emulation.empty() || ctx.arg.is64)
305355764e3SGeorge Rimar       return 0;
3061dd9a565SFangrui Song     return ctx.arg.mipsN32Abi ? EF_MIPS_ABI2 : EF_MIPS_ABI_O32;
307355764e3SGeorge Rimar   }
3086d03a690SFangrui Song   checkFlags(ctx, v);
309e24457a3SFangrui Song   return getMiscFlags(v) | getPicFlags(ctx, v) | getArchFlags(ctx, v);
310f3e3629fSKonstantin Zhuravlyov }
311f3e3629fSKonstantin Zhuravlyov 
3123837f427SRui Ueyama static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
3133837f427SRui Ueyama   if (fpA == fpB)
314f3e3629fSKonstantin Zhuravlyov     return 0;
3153837f427SRui Ueyama   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
316f3e3629fSKonstantin Zhuravlyov     return 1;
3173837f427SRui Ueyama   if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
3183837f427SRui Ueyama       fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
319f3e3629fSKonstantin Zhuravlyov     return 1;
3203837f427SRui Ueyama   if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
321f3e3629fSKonstantin Zhuravlyov     return -1;
3223837f427SRui Ueyama   if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
3233837f427SRui Ueyama       fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
3243837f427SRui Ueyama       fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
325f3e3629fSKonstantin Zhuravlyov     return 1;
326f3e3629fSKonstantin Zhuravlyov   return -1;
327f3e3629fSKonstantin Zhuravlyov }
328f3e3629fSKonstantin Zhuravlyov 
3293837f427SRui Ueyama static StringRef getMipsFpAbiName(uint8_t fpAbi) {
3303837f427SRui Ueyama   switch (fpAbi) {
331f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_ANY:
332f3e3629fSKonstantin Zhuravlyov     return "any";
333f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
334f3e3629fSKonstantin Zhuravlyov     return "-mdouble-float";
335f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
336f3e3629fSKonstantin Zhuravlyov     return "-msingle-float";
337f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
338f3e3629fSKonstantin Zhuravlyov     return "-msoft-float";
339f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
34064fb2901SSimon Atanasyan     return "-mgp32 -mfp64 (old)";
341f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_XX:
342f3e3629fSKonstantin Zhuravlyov     return "-mfpxx";
343f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_64:
344f3e3629fSKonstantin Zhuravlyov     return "-mgp32 -mfp64";
345f3e3629fSKonstantin Zhuravlyov   case Mips::Val_GNU_MIPS_ABI_FP_64A:
346f3e3629fSKonstantin Zhuravlyov     return "-mgp32 -mfp64 -mno-odd-spreg";
347f3e3629fSKonstantin Zhuravlyov   default:
348f3e3629fSKonstantin Zhuravlyov     return "unknown";
349f3e3629fSKonstantin Zhuravlyov   }
350f3e3629fSKonstantin Zhuravlyov }
351f3e3629fSKonstantin Zhuravlyov 
352*c4dc5ed8SFangrui Song uint8_t elf::getMipsFpAbiFlag(Ctx &ctx, InputFile *file, uint8_t oldFlag,
353*c4dc5ed8SFangrui Song                               uint8_t newFlag) {
3543837f427SRui Ueyama   if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
3553837f427SRui Ueyama     return newFlag;
3563837f427SRui Ueyama   if (compareMipsFpAbi(oldFlag, newFlag) < 0)
357*c4dc5ed8SFangrui Song     Err(ctx) << file << ": floating point ABI '" << getMipsFpAbiName(newFlag)
35809c2c5e1SFangrui Song              << "' is incompatible with target floating point ABI '"
35909c2c5e1SFangrui Song              << getMipsFpAbiName(oldFlag) << "'";
3603837f427SRui Ueyama   return oldFlag;
361f3e3629fSKonstantin Zhuravlyov }
362f3e3629fSKonstantin Zhuravlyov 
3636d03a690SFangrui Song template <class ELFT> static bool isN32Abi(const InputFile &f) {
3646d03a690SFangrui Song   if (auto *ef = dyn_cast<ELFFileBase>(&f))
3654845531fSGeorgii Rymar     return ef->template getObj<ELFT>().getHeader().e_flags & EF_MIPS_ABI2;
366f3e3629fSKonstantin Zhuravlyov   return false;
367f3e3629fSKonstantin Zhuravlyov }
368f3e3629fSKonstantin Zhuravlyov 
3696d03a690SFangrui Song bool elf::isMipsN32Abi(Ctx &ctx, const InputFile &f) {
3701dd9a565SFangrui Song   switch (ctx.arg.ekind) {
371f3e3629fSKonstantin Zhuravlyov   case ELF32LEKind:
3723837f427SRui Ueyama     return isN32Abi<ELF32LE>(f);
373f3e3629fSKonstantin Zhuravlyov   case ELF32BEKind:
3743837f427SRui Ueyama     return isN32Abi<ELF32BE>(f);
375f3e3629fSKonstantin Zhuravlyov   case ELF64LEKind:
3763837f427SRui Ueyama     return isN32Abi<ELF64LE>(f);
377f3e3629fSKonstantin Zhuravlyov   case ELF64BEKind:
3783837f427SRui Ueyama     return isN32Abi<ELF64BE>(f);
379f3e3629fSKonstantin Zhuravlyov   default:
380b8248dacSFangrui Song     llvm_unreachable("unknown ctx.arg.ekind");
381f3e3629fSKonstantin Zhuravlyov   }
382f3e3629fSKonstantin Zhuravlyov }
383f3e3629fSKonstantin Zhuravlyov 
384b3e0bd3dSFangrui Song bool elf::isMicroMips(Ctx &ctx) { return ctx.arg.eflags & EF_MIPS_MICROMIPS; }
385cfa8aa7eSSimon Atanasyan 
3866d03a690SFangrui Song bool elf::isMipsR6(Ctx &ctx) {
3871dd9a565SFangrui Song   uint32_t arch = ctx.arg.eflags & EF_MIPS_ARCH;
3883837f427SRui Ueyama   return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
389f8db4536SSimon Atanasyan }
390f8db4536SSimon Atanasyan 
3916d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF32LE>(Ctx &);
3926d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF32BE>(Ctx &);
3936d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF64LE>(Ctx &);
3946d03a690SFangrui Song template uint32_t elf::calcMipsEFlags<ELF64BE>(Ctx &);
395