Coverage Report

Created: 2019-01-18 03:29

/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
191
static void checkFlags(ArrayRef<FileFlags> Files) {
68
191
  assert(!Files.empty() && "expected non-empty file list");
69
191
70
191
  uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
71
191
  bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
72
191
  bool Fp = Files[0].Flags & EF_MIPS_FP64;
73
191
74
250
  for (const FileFlags &F : Files) {
75
250
    if (Config->Is64 && 
F.Flags & EF_MIPS_MICROMIPS62
)
76
2
      error(toString(F.File) + ": microMIPS 64-bit is not supported");
77
250
78
250
    uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
79
250
    if (ABI != ABI2)
80
4
      error(toString(F.File) + ": ABI '" + getAbiName(ABI2) +
81
4
            "' is incompatible with target ABI '" + getAbiName(ABI) + "'");
82
250
83
250
    bool Nan2 = F.Flags & EF_MIPS_NAN2008;
84
250
    if (Nan != Nan2)
85
1
      error(toString(F.File) + ": -mnan=" + getNanName(Nan2) +
86
1
            " is incompatible with target -mnan=" + getNanName(Nan));
87
250
88
250
    bool Fp2 = F.Flags & EF_MIPS_FP64;
89
250
    if (Fp != Fp2)
90
2
      error(toString(F.File) + ": -mfp" + getFpName(Fp2) +
91
2
            " is incompatible with target -mfp" + getFpName(Fp));
92
250
  }
93
191
}
94
95
191
static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
96
191
  uint32_t Ret = 0;
97
191
  for (const FileFlags &F : Files)
98
250
    Ret |= F.Flags &
99
250
           (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
100
250
            EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
101
191
  return Ret;
102
191
}
103
104
191
static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
105
191
  // Check PIC/non-PIC compatibility.
106
191
  bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
107
191
  for (const FileFlags &F : Files.slice(1)) {
108
59
    bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
109
59
    if (IsPic && 
!IsPic252
)
110
1
      warn(toString(F.File) +
111
1
           ": linking non-abicalls code with abicalls code " +
112
1
           toString(Files[0].File));
113
59
    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
59
  }
118
191
119
191
  // Compute the result PIC/non-PIC flag.
120
191
  uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
121
191
  for (const FileFlags &F : Files.slice(1))
122
59
    Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
123
191
124
191
  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
125
191
  if (Ret & EF_MIPS_PIC)
126
28
    Ret |= EF_MIPS_CPIC;
127
191
  return Ret;
128
191
}
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
66
static bool isArchMatched(uint32_t New, uint32_t Res) {
171
66
  if (New == Res)
172
55
    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
191
static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
279
191
  uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
280
191
281
191
  for (const FileFlags &F : Files.slice(1)) {
282
59
    uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
283
59
284
59
    // Check ISA compatibility.
285
59
    if (isArchMatched(New, Ret))
286
55
      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
191
  
return Ret189
;
296
191
}
297
298
192
template <class ELFT> uint32_t elf::calcMipsEFlags() {
299
192
  std::vector<FileFlags> V;
300
192
  for (InputFile *F : ObjectFiles)
301
250
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
302
192
  if (V.empty())
303
1
    return 0;
304
191
  checkFlags(V);
305
191
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
306
191
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)1, false> >()
Line
Count
Source
298
23
template <class ELFT> uint32_t elf::calcMipsEFlags() {
299
23
  std::vector<FileFlags> V;
300
23
  for (InputFile *F : ObjectFiles)
301
28
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
302
23
  if (V.empty())
303
0
    return 0;
304
23
  checkFlags(V);
305
23
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
306
23
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)0, false> >()
Line
Count
Source
298
121
template <class ELFT> uint32_t elf::calcMipsEFlags() {
299
121
  std::vector<FileFlags> V;
300
121
  for (InputFile *F : ObjectFiles)
301
160
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
302
121
  if (V.empty())
303
1
    return 0;
304
120
  checkFlags(V);
305
120
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
306
120
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)1, true> >()
Line
Count
Source
298
3
template <class ELFT> uint32_t elf::calcMipsEFlags() {
299
3
  std::vector<FileFlags> V;
300
3
  for (InputFile *F : ObjectFiles)
301
3
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
302
3
  if (V.empty())
303
0
    return 0;
304
3
  checkFlags(V);
305
3
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
306
3
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)0, true> >()
Line
Count
Source
298
45
template <class ELFT> uint32_t elf::calcMipsEFlags() {
299
45
  std::vector<FileFlags> V;
300
45
  for (InputFile *F : ObjectFiles)
301
59
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
302
45
  if (V.empty())
303
0
    return 0;
304
45
  checkFlags(V);
305
45
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
306
45
}
307
308
245
static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
309
245
  if (FpA == FpB)
310
51
    return 0;
311
194
  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
312
186
    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
241
                              StringRef FileName) {
350
241
  if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
351
237
    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
466
template <class ELFT> static bool isN32Abi(const InputFile *F) {
360
466
  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361
466
    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
48
template <class ELFT> static bool isN32Abi(const InputFile *F) {
360
48
  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361
48
    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
303
template <class ELFT> static bool isN32Abi(const InputFile *F) {
360
303
  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361
303
    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
4
template <class ELFT> static bool isN32Abi(const InputFile *F) {
360
4
  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361
4
    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
111
template <class ELFT> static bool isN32Abi(const InputFile *F) {
360
111
  if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))
361
111
    return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;
362
0
  return false;
363
0
}
364
365
466
bool elf::isMipsN32Abi(const InputFile *F) {
366
466
  switch (Config->EKind) {
367
466
  case ELF32LEKind:
368
48
    return isN32Abi<ELF32LE>(F);
369
466
  case ELF32BEKind:
370
303
    return isN32Abi<ELF32BE>(F);
371
466
  case ELF64LEKind:
372
4
    return isN32Abi<ELF64LE>(F);
373
466
  case ELF64BEKind:
374
111
    return isN32Abi<ELF64BE>(F);
375
466
  default:
376
0
    llvm_unreachable("unknown Config->EKind");
377
466
  }
378
466
}
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>();