]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
Vendor import of lld trunk r233088:
[FreeBSD/FreeBSD.git] / lib / ReaderWriter / ELF / Mips / MipsELFFlagsMerger.cpp
1 //===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.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 #include "MipsELFFlagsMerger.h"
11 #include "lld/Core/Error.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/Support/ELF.h"
14 #include "llvm/Support/raw_ostream.h"
15
16 using namespace lld;
17 using namespace lld::elf;
18 using namespace llvm::ELF;
19
20 struct MipsISATreeEdge {
21   unsigned child;
22   unsigned parent;
23 };
24
25 static MipsISATreeEdge isaTree[] = {
26     // MIPS32R6 and MIPS64R6 are not compatible with other extensions
27
28     // MIPS64 extensions.
29     {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
30     // MIPS V extensions.
31     {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
32     // MIPS IV extensions.
33     {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
34     // MIPS III extensions.
35     {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
36     // MIPS32 extensions.
37     {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
38     // MIPS II extensions.
39     {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
40     {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
41     // MIPS I extensions.
42     {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
43 };
44
45 static bool matchMipsISA(unsigned base, unsigned ext) {
46   if (base == ext)
47     return true;
48   if (base == EF_MIPS_ARCH_32 && matchMipsISA(EF_MIPS_ARCH_64, ext))
49     return true;
50   if (base == EF_MIPS_ARCH_32R2 && matchMipsISA(EF_MIPS_ARCH_64R2, ext))
51     return true;
52   for (const auto &edge : isaTree) {
53     if (ext == edge.child) {
54       ext = edge.parent;
55       if (ext == base)
56         return true;
57     }
58   }
59   return false;
60 }
61
62 MipsELFFlagsMerger::MipsELFFlagsMerger(bool is64Bits)
63     : _is64Bit(is64Bits), _flags(0) {}
64
65 uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
66
67 std::error_code MipsELFFlagsMerger::merge(uint8_t newClass, uint32_t newFlags) {
68   // Check bitness.
69   if (_is64Bit != (newClass == ELFCLASS64))
70     return make_dynamic_error_code(
71         Twine("Bitness is incompatible with that of the selected target"));
72
73   // We support two ABI: O32 and N64. The last one does not have
74   // the corresponding ELF flag.
75   uint32_t inAbi = newFlags & EF_MIPS_ABI;
76   uint32_t supportedAbi = _is64Bit ? 0 : uint32_t(EF_MIPS_ABI_O32);
77   if (inAbi != supportedAbi)
78     return make_dynamic_error_code(Twine("Unsupported ABI"));
79
80   // ... and reduced set of architectures ...
81   uint32_t newArch = newFlags & EF_MIPS_ARCH;
82   switch (newArch) {
83   case EF_MIPS_ARCH_1:
84   case EF_MIPS_ARCH_2:
85   case EF_MIPS_ARCH_3:
86   case EF_MIPS_ARCH_4:
87   case EF_MIPS_ARCH_5:
88   case EF_MIPS_ARCH_32:
89   case EF_MIPS_ARCH_64:
90   case EF_MIPS_ARCH_32R2:
91   case EF_MIPS_ARCH_64R2:
92   case EF_MIPS_ARCH_32R6:
93   case EF_MIPS_ARCH_64R6:
94     break;
95   default:
96     return make_dynamic_error_code(Twine("Unsupported instruction set"));
97   }
98
99   // ... and still do not support MIPS-16 extension.
100   if (newFlags & EF_MIPS_ARCH_ASE_M16)
101     return make_dynamic_error_code(Twine("Unsupported extension: MIPS16"));
102
103   // PIC code is inherently CPIC and may not set CPIC flag explicitly.
104   // Ensure that this flag will exist in the linked file.
105   if (newFlags & EF_MIPS_PIC)
106     newFlags |= EF_MIPS_CPIC;
107
108   std::lock_guard<std::mutex> lock(_mutex);
109
110   // If the old set of flags is empty, use the new one as a result.
111   if (!_flags) {
112     _flags = newFlags;
113     return std::error_code();
114   }
115
116   // Check PIC / CPIC flags compatibility.
117   uint32_t newPic = newFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
118   uint32_t oldPic = _flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
119
120   if ((newPic != 0) != (oldPic != 0))
121     llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
122
123   if (!(newPic & EF_MIPS_PIC))
124     _flags &= ~EF_MIPS_PIC;
125   if (newPic)
126     _flags |= EF_MIPS_CPIC;
127
128   // Check mixing -mnan=2008 / -mnan=legacy modules.
129   if ((newFlags & EF_MIPS_NAN2008) != (_flags & EF_MIPS_NAN2008))
130     return make_dynamic_error_code(
131         Twine("Linking -mnan=2008 and -mnan=legacy modules"));
132
133   // Check ISA compatibility and update the extension flag.
134   uint32_t oldArch = _flags & EF_MIPS_ARCH;
135   if (!matchMipsISA(newArch, oldArch)) {
136     if (!matchMipsISA(oldArch, newArch))
137       return make_dynamic_error_code(
138           Twine("Linking modules with incompatible ISA"));
139     _flags &= ~EF_MIPS_ARCH;
140     _flags |= newArch;
141   }
142
143   _flags |= newFlags & EF_MIPS_NOREORDER;
144   _flags |= newFlags & EF_MIPS_MICROMIPS;
145   _flags |= newFlags & EF_MIPS_NAN2008;
146   _flags |= newFlags & EF_MIPS_32BITMODE;
147
148   return std::error_code();
149 }