Coverage Report

Created: 2019-05-19 14:56

/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
196
static void checkFlags(ArrayRef<FileFlags> Files) {
67
196
  assert(!Files.empty() && "expected non-empty file list");
68
196
69
196
  uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
70
196
  bool Nan = Files[0].Flags & EF_MIPS_NAN2008;
71
196
  bool Fp = Files[0].Flags & EF_MIPS_FP64;
72
196
73
262
  for (const FileFlags &F : Files) {
74
262
    if (Config->Is64 && 
F.Flags & EF_MIPS_MICROMIPS62
)
75
2
      error(toString(F.File) + ": microMIPS 64-bit is not supported");
76
262
77
262
    uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
78
262
    if (ABI != ABI2)
79
4
      error(toString(F.File) + ": ABI '" + getAbiName(ABI2) +
80
4
            "' is incompatible with target ABI '" + getAbiName(ABI) + "'");
81
262
82
262
    bool Nan2 = F.Flags & EF_MIPS_NAN2008;
83
262
    if (Nan != Nan2)
84
1
      error(toString(F.File) + ": -mnan=" + getNanName(Nan2) +
85
1
            " is incompatible with target -mnan=" + getNanName(Nan));
86
262
87
262
    bool Fp2 = F.Flags & EF_MIPS_FP64;
88
262
    if (Fp != Fp2)
89
2
      error(toString(F.File) + ": -mfp" + getFpName(Fp2) +
90
2
            " is incompatible with target -mfp" + getFpName(Fp));
91
262
  }
92
196
}
93
94
196
static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {
95
196
  uint32_t Ret = 0;
96
196
  for (const FileFlags &F : Files)
97
262
    Ret |= F.Flags &
98
262
           (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
99
262
            EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
100
196
  return Ret;
101
196
}
102
103
196
static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {
104
196
  // Check PIC/non-PIC compatibility.
105
196
  bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
106
196
  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
196
118
196
  // Compute the result PIC/non-PIC flag.
119
196
  uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
120
196
  for (const FileFlags &F : Files.slice(1))
121
66
    Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
122
196
123
196
  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
124
196
  if (Ret & EF_MIPS_PIC)
125
28
    Ret |= EF_MIPS_CPIC;
126
196
  return Ret;
127
196
}
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
196
static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {
278
196
  uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
279
196
280
196
  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
196
  
return Ret194
;
295
196
}
296
297
197
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
197
  std::vector<FileFlags> V;
299
197
  for (InputFile *F : ObjectFiles)
300
262
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
301
197
  if (V.empty())
302
1
    return 0;
303
196
  checkFlags(V);
304
196
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
305
196
}
unsigned int lld::elf::calcMipsEFlags<llvm::object::ELFType<(llvm::support::endianness)1, false> >()
Line
Count
Source
297
23
template <class ELFT> uint32_t elf::calcMipsEFlags() {
298
23
  std::vector<FileFlags> V;
299
23
  for (InputFile *F : ObjectFiles)
300
28
    V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});
301
23
  if (V.empty())
302
0
    return 0;
303
23
  checkFlags(V);
304
23
  return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
305
23
}
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
257
static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {
308
257
  if (FpA == FpB)
309
58
    return 0;
310
199
  if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
311
191
    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
253
                              StringRef FileName) {
349
253
  if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)
350
249
    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
482
template <class ELFT> static bool isN32Abi(const InputFile *F) {
359
482
  if (auto *EF = dyn_cast<ELFFileBase>(F))
360
482
    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
48
template <class ELFT> static bool isN32Abi(const InputFile *F) {
359
48
  if (auto *EF = dyn_cast<ELFFileBase>(F))
360
48
    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
482
bool elf::isMipsN32Abi(const InputFile *F) {
365
482
  switch (Config->EKind) {
366
482
  case ELF32LEKind:
367
48
    return isN32Abi<ELF32LE>(F);
368
482
  case ELF32BEKind:
369
319
    return isN32Abi<ELF32BE>(F);
370
482
  case ELF64LEKind:
371
4
    return isN32Abi<ELF64LE>(F);
372
482
  case ELF64BEKind:
373
111
    return isN32Abi<ELF64BE>(F);
374
482
  default:
375
0
    llvm_unreachable("unknown Config->EKind");
376
482
  }
377
482
}
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>();