Coverage Report

Created: 2018-01-17 17:22

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