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