Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/Arch/MipsArchTree.cpp
Line
Count
Source (jump to first uncovered line)
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
41
8
static StringRef getAbiName(uint32_t flags) {
42
8
  switch (flags) {
43
8
  case 0:
44
2
    return "n64";
45
8
  case EF_MIPS_ABI2:
46
0
    return "n32";
47
8
  case EF_MIPS_ABI_O32:
48
2
    return "o32";
49
8
  case EF_MIPS_ABI_O64:
50
1
    return "o64";
51
8
  case EF_MIPS_ABI_EABI32:
52
2
    return "eabi32";
53
8
  case EF_MIPS_ABI_EABI64:
54
1
    return "eabi64";
55
8
  default:
56
0
    return "unknown";
57
8
  }
58
8
}
59
60
2
static StringRef getNanName(bool isNan2008) {
61
2
  return isNan2008 ? 
"2008"1
:
"legacy"1
;
62
2
}
63
64
4
static StringRef getFpName(bool isFp64) { return isFp64 ? 
"64"2
:
"32"2
; }
65
66
197
static void checkFlags(ArrayRef<FileFlags> files) {
67
197
  assert(!files.empty() && "expected non-empty file list");
68
197
69
197
  uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
70
197
  bool nan = files[0].flags & EF_MIPS_NAN2008;
71
197
  bool fp = files[0].flags & EF_MIPS_FP64;
72
197
73
263
  for (const FileFlags &f : files) {
74
263
    if (config->is64 && 
f.flags & EF_MIPS_MICROMIPS62
)
75
2
      error(toString(f.file) + ": microMIPS 64-bit is not supported");
76
263
77
263
    uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
78
263
    if (abi != abi2)
79
4
      error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
80
4
            "' is incompatible with target ABI '" + getAbiName(abi) + "'");
81
263
82
263
    bool nan2 = f.flags & EF_MIPS_NAN2008;
83
263
    if (nan != nan2)
84
1
      error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
85
1
            " is incompatible with target -mnan=" + getNanName(nan));
86
263
87
263
    bool fp2 = f.flags & EF_MIPS_FP64;
88
263
    if (fp != fp2)
89
2
      error(toString(f.file) + ": -mfp" + getFpName(fp2) +
90
2
            " is incompatible with target -mfp" + getFpName(fp));
91
263
  }
92
197
}
93
94
197
static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
95
197
  uint32_t ret = 0;
96
197
  for (const FileFlags &f : files)
97
263
    ret |= f.flags &
98
263
           (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
99
263
            EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
100
197
  return ret;
101
197
}
102
103
197
static uint32_t getPicFlags(ArrayRef<FileFlags> files) {
104
197
  // Check PIC/non-PIC compatibility.
105
197
  bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
106
197
  for (const FileFlags &f : files.slice(1)) {
107
66
    bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
108
66
    if (isPic && 
!isPic259
)
109
1
      warn(toString(f.file) +
110
1
           ": linking non-abicalls code with abicalls code " +
111
1
           toString(files[0].file));
112
66
    if (!isPic && 
isPic27
)
113
1
      warn(toString(f.file) +
114
1
           ": linking abicalls code with non-abicalls code " +
115
1
           toString(files[0].file));
116
66
  }
117
197
118
197
  // Compute the result PIC/non-PIC flag.
119
197
  uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
120
197
  for (const FileFlags &f : files.slice(1))
121
66
    ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
122
197
123
197
  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
124
197
  if (ret & EF_MIPS_PIC)
125
28
    ret |= EF_MIPS_CPIC;
126
197
  return ret;
127
197
}
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
169
73
static bool isArchMatched(uint32_t New, uint32_t res) {
170
73
  if (New == res)
171
62
    return true;
172
11
  if (New == EF_MIPS_ARCH_32 && 
isArchMatched(EF_MIPS_ARCH_64, res)2
)
173
0
    return true;
174
11
  if (New == EF_MIPS_ARCH_32R2 && 
isArchMatched(EF_MIPS_ARCH_64R2, res)1
)
175
0
    return true;
176
263
  
for (const auto &edge : archTree)11
{
177
263
    if (res == edge.child) {
178
28
      res = edge.parent;
179
28
      if (res == New)
180
2
        return true;
181
28
    }
182
263
  }
183
11
  
return false9
;
184
11
}
185
186
4
static StringRef getMachName(uint32_t flags) {
187
4
  switch (flags & EF_MIPS_MACH) {
188
4
  case EF_MIPS_MACH_NONE:
189
3
    return "";
190
4
  case EF_MIPS_MACH_3900:
191
0
    return "r3900";
192
4
  case EF_MIPS_MACH_4010:
193
0
    return "r4010";
194
4
  case EF_MIPS_MACH_4100:
195
0
    return "r4100";
196
4
  case EF_MIPS_MACH_4650:
197
0
    return "r4650";
198
4
  case EF_MIPS_MACH_4120:
199
0
    return "r4120";
200
4
  case EF_MIPS_MACH_4111:
201
0
    return "r4111";
202
4
  case EF_MIPS_MACH_5400:
203
0
    return "vr5400";
204
4
  case EF_MIPS_MACH_5900:
205
0
    return "vr5900";
206
4
  case EF_MIPS_MACH_5500:
207
0
    return "vr5500";
208
4
  case EF_MIPS_MACH_9000:
209
0
    return "rm9000";
210
4
  case EF_MIPS_MACH_LS2E:
211
0
    return "loongson2e";
212
4
  case EF_MIPS_MACH_LS2F:
213
0
    return "loongson2f";
214
4
  case EF_MIPS_MACH_LS3A:
215
0
    return "loongson3a";
216
4
  case EF_MIPS_MACH_OCTEON:
217
1
    return "octeon";
218
4
  case EF_MIPS_MACH_OCTEON2:
219
0
    return "octeon2";
220
4
  case EF_MIPS_MACH_OCTEON3:
221
0
    return "octeon3";
222
4
  case EF_MIPS_MACH_SB1:
223
0
    return "sb1";
224
4
  case EF_MIPS_MACH_XLR:
225
0
    return "xlr";
226
4
  default:
227
0
    return "unknown machine";
228
4
  }
229
4
}
230
231
4
static StringRef getArchName(uint32_t flags) {
232
4
  switch (flags & EF_MIPS_ARCH) {
233
4
  case EF_MIPS_ARCH_1:
234
0
    return "mips1";
235
4
  case EF_MIPS_ARCH_2:
236
0
    return "mips2";
237
4
  case EF_MIPS_ARCH_3:
238
1
    return "mips3";
239
4
  case EF_MIPS_ARCH_4:
240
0
    return "mips4";
241
4
  case EF_MIPS_ARCH_5:
242
0
    return "mips5";
243
4
  case EF_MIPS_ARCH_32:
244
1
    return "mips32";
245
4
  case EF_MIPS_ARCH_64:
246
0
    return "mips64";
247
4
  case EF_MIPS_ARCH_32R2:
248
0
    return "mips32r2";
249
4
  case EF_MIPS_ARCH_64R2:
250
1
    return "mips64r2";
251
4
  case EF_MIPS_ARCH_32R6:
252
0
    return "mips32r6";
253
4
  case EF_MIPS_ARCH_64R6:
254
1
    return "mips64r6";
255
4
  default:
256
0
    return "unknown arch";
257
4
  }
258
4
}
259
260
4
static std::string getFullArchName(uint32_t flags) {
261
4
  StringRef arch = getArchName(flags);
262
4
  StringRef mach = getMachName(flags);
263
4
  if (mach.empty())
264
3
    return arch.str();
265
1
  return (arch + " (" + mach + ")").str();
266
1
}
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.
277
197
static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
278
197
  uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
279
197
280
197
  for (const FileFlags &f : files.slice(1)) {
281
66
    uint32_t New = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
282
66
283
66
    // Check ISA compatibility.
284
66
    if (isArchMatched(New, ret))
285
62
      continue;
286
4
    if (!isArchMatched(ret, New)) {
287
2
      error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
288
2
            getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
289
2
            getFullArchName(New));
290
2
      return 0;
291
2
    }
292
2
    ret = New;
293
2
  }
294
197
  
return ret195
;
295
197
}
296
297
198
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
198
  std::vector<FileFlags> v;
299
198
  for (InputFile *f : objectFiles)
300
263
    v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
301
198
  if (v.empty())
302
1
    return 0;
303
197
  checkFlags(v);
304
197
  return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
305
197
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)1, false> >()
Line
Count
Source
297
24
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
24
  std::vector<FileFlags> v;
299
24
  for (InputFile *f : objectFiles)
300
29
    v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
301
24
  if (v.empty())
302
0
    return 0;
303
24
  checkFlags(v);
304
24
  return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
305
24
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)0, false> >()
Line
Count
Source
297
126
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
126
  std::vector<FileFlags> v;
299
126
  for (InputFile *f : objectFiles)
300
172
    v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
301
126
  if (v.empty())
302
1
    return 0;
303
125
  checkFlags(v);
304
125
  return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
305
125
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)1, true> >()
Line
Count
Source
297
3
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
3
  std::vector<FileFlags> v;
299
3
  for (InputFile *f : objectFiles)
300
3
    v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
301
3
  if (v.empty())
302
0
    return 0;
303
3
  checkFlags(v);
304
3
  return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
305
3
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)0, true> >()
Line
Count
Source
297
45
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
45
  std::vector<FileFlags> v;
299
45
  for (InputFile *f : objectFiles)
300
59
    v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
301
45
  if (v.empty())
302
0
    return 0;
303
45
  checkFlags(v);
304
45
  return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
305
45
}
306
307
258
static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
308
258
  if (fpA == fpB)
309
58
    return 0;
310
200
  if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
311
192
    return 1;
312
8
  if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
313
8
      
fpA == Mips::Val_GNU_MIPS_ABI_FP_641
)
314
0
    return 1;
315
8
  if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
316
7
    return -1;
317
1
  if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
318
1
      fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
319
1
      fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
320
0
    return 1;
321
1
  return -1;
322
1
}
323
324
8
static StringRef getMipsFpAbiName(uint8_t fpAbi) {
325
8
  switch (fpAbi) {
326
8
  case Mips::Val_GNU_MIPS_ABI_FP_ANY:
327
0
    return "any";
328
8
  case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
329
1
    return "-mdouble-float";
330
8
  case Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
331
2
    return "-msingle-float";
332
8
  case Mips::Val_GNU_MIPS_ABI_FP_SOFT:
333
1
    return "-msoft-float";
334
8
  case Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
335
1
    return "-mgp32 -mfp64 (old)";
336
8
  case Mips::Val_GNU_MIPS_ABI_FP_XX:
337
1
    return "-mfpxx";
338
8
  case Mips::Val_GNU_MIPS_ABI_FP_64:
339
1
    return "-mgp32 -mfp64";
340
8
  case Mips::Val_GNU_MIPS_ABI_FP_64A:
341
1
    return "-mgp32 -mfp64 -mno-odd-spreg";
342
8
  default:
343
0
    return "unknown";
344
8
  }
345
8
}
346
347
uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
348
254
                              StringRef fileName) {
349
254
  if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
350
250
    return newFlag;
351
4
  if (compareMipsFpAbi(oldFlag, newFlag) < 0)
352
4
    error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
353
4
          "' is incompatible with target floating point ABI '" +
354
4
          getMipsFpAbiName(oldFlag) + "'");
355
4
  return oldFlag;
356
4
}
357
358
484
template <class ELFT> static bool isN32Abi(const InputFile *f) {
359
484
  if (auto *ef = dyn_cast<ELFFileBase>(f))
360
484
    return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
361
0
  return false;
362
0
}
MipsArchTree.cpp:bool isN32Abi<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::InputFile const*)
Line
Count
Source
358
50
template <class ELFT> static bool isN32Abi(const InputFile *f) {
359
50
  if (auto *ef = dyn_cast<ELFFileBase>(f))
360
50
    return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
361
0
  return false;
362
0
}
MipsArchTree.cpp:bool isN32Abi<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::InputFile const*)
Line
Count
Source
358
319
template <class ELFT> static bool isN32Abi(const InputFile *f) {
359
319
  if (auto *ef = dyn_cast<ELFFileBase>(f))
360
319
    return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
361
0
  return false;
362
0
}
MipsArchTree.cpp:bool isN32Abi<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::InputFile const*)
Line
Count
Source
358
4
template <class ELFT> static bool isN32Abi(const InputFile *f) {
359
4
  if (auto *ef = dyn_cast<ELFFileBase>(f))
360
4
    return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
361
0
  return false;
362
0
}
MipsArchTree.cpp:bool isN32Abi<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::InputFile const*)
Line
Count
Source
358
111
template <class ELFT> static bool isN32Abi(const InputFile *f) {
359
111
  if (auto *ef = dyn_cast<ELFFileBase>(f))
360
111
    return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
361
0
  return false;
362
0
}
363
364
484
bool elf::isMipsN32Abi(const InputFile *f) {
365
484
  switch (config->ekind) {
366
484
  case ELF32LEKind:
367
50
    return isN32Abi<ELF32LE>(f);
368
484
  case ELF32BEKind:
369
319
    return isN32Abi<ELF32BE>(f);
370
484
  case ELF64LEKind:
371
4
    return isN32Abi<ELF64LE>(f);
372
484
  case ELF64BEKind:
373
111
    return isN32Abi<ELF64BE>(f);
374
484
  default:
375
0
    llvm_unreachable("unknown Config->EKind");
376
484
  }
377
484
}
378
379
33.1k
bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
380
381
34
bool elf::isMipsR6() {
382
34
  uint32_t arch = config->eflags & EF_MIPS_ARCH;
383
34
  return arch == EF_MIPS_ARCH_32R6 || 
arch == EF_MIPS_ARCH_64R624
;
384
34
}
385
386
template uint32_t elf::calcMipsEFlags<ELF32LE>();
387
template uint32_t elf::calcMipsEFlags<ELF32BE>();
388
template uint32_t elf::calcMipsEFlags<ELF64LE>();
389
template uint32_t elf::calcMipsEFlags<ELF64BE>();