12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " llvm/Object/MachOUniversalWriter.h"
15
+ #include " llvm/ADT/Triple.h"
15
16
#include " llvm/Object/Archive.h"
16
17
#include " llvm/Object/Binary.h"
17
18
#include " llvm/Object/Error.h"
19
+ #include " llvm/Object/IRObjectFile.h"
18
20
#include " llvm/Object/MachO.h"
19
21
#include " llvm/Object/MachOUniversal.h"
20
22
#include " llvm/Support/FileOutputBuffer.h"
@@ -79,13 +81,36 @@ Slice::Slice(const MachOObjectFile &O, uint32_t Align)
79
81
ArchName(std::string(O.getArchTriple().getArchName())),
80
82
P2Alignment(Align) {}
81
83
84
+ Slice::Slice (const IRObjectFile *IRO, uint32_t CPUType, uint32_t CPUSubType,
85
+ std::string ArchName, uint32_t Align)
86
+ : B(IRO), CPUType(CPUType), CPUSubType(CPUSubType),
87
+ ArchName(std::move(ArchName)), P2Alignment(Align) {}
88
+
82
89
Slice::Slice (const MachOObjectFile &O) : Slice(O, calculateAlignment(O)) {}
83
90
84
- Expected<Slice> Slice::create (const Archive *A) {
91
+ using MachoCPUTy = std::pair<unsigned , unsigned >;
92
+
93
+ static Expected<MachoCPUTy> getMachoCPUFromTriple (Triple TT) {
94
+ auto CPU = std::make_pair (MachO::getCPUType (TT), MachO::getCPUSubType (TT));
95
+ if (!CPU.first ) {
96
+ return CPU.first .takeError ();
97
+ }
98
+ if (!CPU.second ) {
99
+ return CPU.second .takeError ();
100
+ }
101
+ return std::make_pair (*CPU.first , *CPU.second );
102
+ }
103
+
104
+ static Expected<MachoCPUTy> getMachoCPUFromTriple (StringRef TT) {
105
+ return getMachoCPUFromTriple (Triple{TT});
106
+ }
107
+
108
+ Expected<Slice> Slice::create (const Archive *A, LLVMContext *LLVMCtx) {
85
109
Error Err = Error::success ();
86
- std::unique_ptr<MachOObjectFile> FO = nullptr ;
110
+ std::unique_ptr<MachOObjectFile> MFO = nullptr ;
111
+ std::unique_ptr<IRObjectFile> IRFO = nullptr ;
87
112
for (const Archive::Child &Child : A->children (Err)) {
88
- Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary ();
113
+ Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary (LLVMCtx );
89
114
if (!ChildOrErr)
90
115
return createFileError (A->getFileName (), ChildOrErr.takeError ());
91
116
Binary *Bin = ChildOrErr.get ().get ();
@@ -95,46 +120,112 @@ Expected<Slice> Slice::create(const Archive *A) {
95
120
" is a fat file (not allowed in an archive)" )
96
121
.str ()
97
122
.c_str ());
98
- if (!Bin->isMachO ())
99
- return createStringError (
100
- std::errc::invalid_argument,
101
- (" archive member " + Bin->getFileName () +
102
- " is not a MachO file (not allowed in an archive)" )
103
- .str ()
104
- .c_str ());
105
- MachOObjectFile *O = cast<MachOObjectFile>(Bin);
106
- if (FO && std::tie (FO->getHeader ().cputype , FO->getHeader ().cpusubtype ) !=
107
- std::tie (O->getHeader ().cputype , O->getHeader ().cpusubtype )) {
108
- return createStringError (
109
- std::errc::invalid_argument,
110
- (" archive member " + O->getFileName () + " cputype (" +
111
- Twine (O->getHeader ().cputype ) + " ) and cpusubtype(" +
112
- Twine (O->getHeader ().cpusubtype ) +
113
- " ) does not match previous archive members cputype (" +
114
- Twine (FO->getHeader ().cputype ) + " ) and cpusubtype(" +
115
- Twine (FO->getHeader ().cpusubtype ) + " ) (all members must match) " +
116
- FO->getFileName ())
117
- .str ()
118
- .c_str ());
119
- }
120
- if (!FO) {
121
- ChildOrErr.get ().release ();
122
- FO.reset (O);
123
- }
123
+ if (Bin->isMachO ()) {
124
+ MachOObjectFile *O = cast<MachOObjectFile>(Bin);
125
+ if (IRFO) {
126
+ return createStringError (
127
+ std::errc::invalid_argument,
128
+ " archive member %s is a MachO, while previous archive member "
129
+ " %s was an IR LLVM object" ,
130
+ O->getFileName ().str ().c_str (), IRFO->getFileName ().str ().c_str ());
131
+ }
132
+ if (MFO &&
133
+ std::tie (MFO->getHeader ().cputype , MFO->getHeader ().cpusubtype ) !=
134
+ std::tie (O->getHeader ().cputype , O->getHeader ().cpusubtype )) {
135
+ return createStringError (
136
+ std::errc::invalid_argument,
137
+ (" archive member " + O->getFileName () + " cputype (" +
138
+ Twine (O->getHeader ().cputype ) + " ) and cpusubtype(" +
139
+ Twine (O->getHeader ().cpusubtype ) +
140
+ " ) does not match previous archive members cputype (" +
141
+ Twine (MFO->getHeader ().cputype ) + " ) and cpusubtype(" +
142
+ Twine (MFO->getHeader ().cpusubtype ) +
143
+ " ) (all members must match) " + MFO->getFileName ())
144
+ .str ()
145
+ .c_str ());
146
+ }
147
+ if (!MFO) {
148
+ ChildOrErr.get ().release ();
149
+ MFO.reset (O);
150
+ }
151
+ } else if (Bin->isIR ()) {
152
+ IRObjectFile *O = cast<IRObjectFile>(Bin);
153
+ if (MFO) {
154
+ return createStringError (std::errc::invalid_argument,
155
+ " archive member '%s' is an LLVM IR object, "
156
+ " while previous archive member "
157
+ " '%s' was a MachO" ,
158
+ O->getFileName ().str ().c_str (),
159
+ MFO->getFileName ().str ().c_str ());
160
+ }
161
+ if (IRFO) {
162
+ Expected<MachoCPUTy> CPUO = getMachoCPUFromTriple (O->getTargetTriple ());
163
+ Expected<MachoCPUTy> CPUFO =
164
+ getMachoCPUFromTriple (IRFO->getTargetTriple ());
165
+ if (!CPUO)
166
+ return CPUO.takeError ();
167
+ if (!CPUFO)
168
+ return CPUFO.takeError ();
169
+ if (*CPUO != *CPUFO) {
170
+ return createStringError (
171
+ std::errc::invalid_argument,
172
+ (" archive member " + O->getFileName () + " cputype (" +
173
+ Twine (CPUO->first ) + " ) and cpusubtype(" + Twine (CPUO->second ) +
174
+ " ) does not match previous archive members cputype (" +
175
+ Twine (CPUFO->first ) + " ) and cpusubtype(" +
176
+ Twine (CPUFO->second ) + " ) (all members must match) " +
177
+ IRFO->getFileName ())
178
+ .str ()
179
+ .c_str ());
180
+ }
181
+ } else {
182
+ ChildOrErr.get ().release ();
183
+ IRFO.reset (O);
184
+ }
185
+ } else
186
+ return createStringError (std::errc::invalid_argument,
187
+ (" archive member " + Bin->getFileName () +
188
+ " is neither a MachO file or an LLVM IR file "
189
+ " (not allowed in an archive)" )
190
+ .str ()
191
+ .c_str ());
124
192
}
125
193
if (Err)
126
194
return createFileError (A->getFileName (), std::move (Err));
127
- if (!FO )
195
+ if (!MFO && !IRFO )
128
196
return createStringError (
129
197
std::errc::invalid_argument,
130
198
(" empty archive with no architecture specification: " +
131
199
A->getFileName () + " (can't determine architecture for it)" )
132
200
.str ()
133
201
.c_str ());
134
202
135
- Slice ArchiveSlice = Slice (*(FO.get ()), FO->is64Bit () ? 3 : 2 );
203
+ if (MFO) {
204
+ Slice ArchiveSlice (*(MFO.get ()), MFO->is64Bit () ? 3 : 2 );
205
+ ArchiveSlice.B = A;
206
+ return ArchiveSlice;
207
+ }
208
+
209
+ // For IR objects
210
+ Expected<Slice> ArchiveSliceOrErr = Slice::create (IRFO.get (), 0 );
211
+ if (!ArchiveSliceOrErr)
212
+ return createFileError (A->getFileName (), ArchiveSliceOrErr.takeError ());
213
+ auto &ArchiveSlice = ArchiveSliceOrErr.get ();
136
214
ArchiveSlice.B = A;
137
- return ArchiveSlice;
215
+ return Slice{std::move (ArchiveSlice)};
216
+ }
217
+
218
+ Expected<Slice> Slice::create (const IRObjectFile *IRO, uint32_t Align) {
219
+ Expected<MachoCPUTy> CPUOrErr = getMachoCPUFromTriple (IRO->getTargetTriple ());
220
+ if (!CPUOrErr)
221
+ return CPUOrErr.takeError ();
222
+ unsigned CPUType, CPUSubType;
223
+ std::tie (CPUType, CPUSubType) = CPUOrErr.get ();
224
+ // We don't directly use the architecture name of the target triple T, as,
225
+ // for instance, thumb is treated as ARM by the MachOUniversal object.
226
+ std::string ArchName (
227
+ MachOObjectFile::getArchTriple (CPUType, CPUSubType).getArchName ());
228
+ return Slice{IRO, CPUType, CPUSubType, std::move (ArchName), Align};
138
229
}
139
230
140
231
static Expected<SmallVector<MachO::fat_arch, 2 >>
0 commit comments