Coverage Report

Created: 2018-08-19 14:04

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