1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #include "llvm/Object/Archive.h"
14 #include "llvm/Object/ArchiveWriter.h"
17 using namespace llvm::object
;
19 struct RustArchiveMember
{
24 RustArchiveMember(): filename(NULL
), name(NULL
),
25 #if LLVM_VERSION_GE(3, 8)
26 child(NULL
, NULL
, NULL
)
31 ~RustArchiveMember() {}
35 struct RustArchiveIterator
{
36 Archive::child_iterator cur
;
37 Archive::child_iterator end
;
38 #if LLVM_VERSION_GE(3, 9)
41 RustArchiveIterator() : err(Error::success()) { }
45 enum class LLVMRustArchiveKind
{
54 from_rust(LLVMRustArchiveKind kind
)
57 case LLVMRustArchiveKind::GNU
:
58 return Archive::K_GNU
;
59 case LLVMRustArchiveKind::MIPS64
:
60 return Archive::K_MIPS64
;
61 case LLVMRustArchiveKind::BSD
:
62 return Archive::K_BSD
;
63 case LLVMRustArchiveKind::COFF
:
64 return Archive::K_COFF
;
66 llvm_unreachable("Bad ArchiveKind.");
70 typedef OwningBinary
<Archive
> *LLVMRustArchiveRef
;
71 typedef RustArchiveMember
*LLVMRustArchiveMemberRef
;
72 typedef Archive::Child
*LLVMRustArchiveChildRef
;
73 typedef Archive::Child
const *LLVMRustArchiveChildConstRef
;
74 typedef RustArchiveIterator
*LLVMRustArchiveIteratorRef
;
76 extern "C" LLVMRustArchiveRef
77 LLVMRustOpenArchive(char *path
) {
78 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> buf_or
= MemoryBuffer::getFile(path
,
82 LLVMRustSetLastError(buf_or
.getError().message().c_str());
86 #if LLVM_VERSION_LE(3, 8)
87 ErrorOr
<std::unique_ptr
<Archive
>> archive_or
=
89 Expected
<std::unique_ptr
<Archive
>> archive_or
=
91 Archive::create(buf_or
.get()->getMemBufferRef());
94 #if LLVM_VERSION_LE(3, 8)
95 LLVMRustSetLastError(archive_or
.getError().message().c_str());
97 LLVMRustSetLastError(toString(archive_or
.takeError()).c_str());
102 OwningBinary
<Archive
> *ret
= new OwningBinary
<Archive
>(
103 std::move(archive_or
.get()), std::move(buf_or
.get()));
109 LLVMRustDestroyArchive(LLVMRustArchiveRef ar
) {
113 extern "C" LLVMRustArchiveIteratorRef
114 LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra
) {
115 Archive
*ar
= ra
->getBinary();
116 RustArchiveIterator
*rai
= new RustArchiveIterator();
117 #if LLVM_VERSION_LE(3, 8)
118 rai
->cur
= ar
->child_begin();
120 rai
->cur
= ar
->child_begin(rai
->err
);
122 LLVMRustSetLastError(toString(std::move(rai
->err
)).c_str());
126 rai
->end
= ar
->child_end();
130 extern "C" LLVMRustArchiveChildConstRef
131 LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai
) {
132 #if LLVM_VERSION_GE(3, 9)
134 LLVMRustSetLastError(toString(std::move(rai
->err
)).c_str());
138 if (rai
->cur
== rai
->end
)
140 #if LLVM_VERSION_EQ(3, 8)
141 const ErrorOr
<Archive::Child
>* cur
= rai
->cur
.operator->();
143 LLVMRustSetLastError(cur
->getError().message().c_str());
146 const Archive::Child
&child
= cur
->get();
148 const Archive::Child
&child
= *rai
->cur
.operator->();
150 Archive::Child
*ret
= new Archive::Child(child
);
157 LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child
) {
162 LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai
) {
166 extern "C" const char*
167 LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child
, size_t *size
) {
168 #if LLVM_VERSION_GE(4, 0)
169 Expected
<StringRef
> name_or_err
= child
->getName();
171 // rustc_llvm currently doesn't use this error string, but it might be useful
172 // in the future, and in the mean time this tells LLVM that the error was
173 // not ignored and that it shouldn't abort the process.
174 LLVMRustSetLastError(toString(name_or_err
.takeError()).c_str());
178 ErrorOr
<StringRef
> name_or_err
= child
->getName();
179 if (name_or_err
.getError())
182 StringRef name
= name_or_err
.get();
187 extern "C" const char*
188 LLVMRustArchiveChildData(LLVMRustArchiveChildRef child
, size_t *size
) {
190 #if LLVM_VERSION_GE(4, 0)
191 Expected
<StringRef
> buf_or_err
= child
->getBuffer();
193 LLVMRustSetLastError(toString(buf_or_err
.takeError()).c_str());
197 ErrorOr
<StringRef
> buf_or_err
= child
->getBuffer();
198 if (buf_or_err
.getError()) {
199 LLVMRustSetLastError(buf_or_err
.getError().message().c_str());
203 buf
= buf_or_err
.get();
208 extern "C" LLVMRustArchiveMemberRef
209 LLVMRustArchiveMemberNew(char *Filename
, char *Name
,
210 LLVMRustArchiveChildRef child
) {
211 RustArchiveMember
*Member
= new RustArchiveMember
;
212 Member
->filename
= Filename
;
215 Member
->child
= *child
;
220 LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member
) {
224 extern "C" LLVMRustResult
225 LLVMRustWriteArchive(char *Dst
,
227 const LLVMRustArchiveMemberRef
*NewMembers
,
229 LLVMRustArchiveKind rust_kind
) {
231 #if LLVM_VERSION_LE(3, 8)
232 std::vector
<NewArchiveIterator
> Members
;
234 std::vector
<NewArchiveMember
> Members
;
236 auto Kind
= from_rust(rust_kind
);
238 for (size_t i
= 0; i
< NumMembers
; i
++) {
239 auto Member
= NewMembers
[i
];
240 assert(Member
->name
);
241 if (Member
->filename
) {
242 #if LLVM_VERSION_GE(3, 9)
243 Expected
<NewArchiveMember
> MOrErr
= NewArchiveMember::getFile(Member
->filename
, true);
245 LLVMRustSetLastError(toString(MOrErr
.takeError()).c_str());
246 return LLVMRustResult::Failure
;
248 Members
.push_back(std::move(*MOrErr
));
249 #elif LLVM_VERSION_EQ(3, 8)
250 Members
.push_back(NewArchiveIterator(Member
->filename
));
252 Members
.push_back(NewArchiveIterator(Member
->filename
, Member
->name
));
255 #if LLVM_VERSION_LE(3, 8)
256 Members
.push_back(NewArchiveIterator(Member
->child
, Member
->name
));
258 Expected
<NewArchiveMember
> MOrErr
= NewArchiveMember::getOldMember(Member
->child
, true);
260 LLVMRustSetLastError(toString(MOrErr
.takeError()).c_str());
261 return LLVMRustResult::Failure
;
263 Members
.push_back(std::move(*MOrErr
));
267 #if LLVM_VERSION_GE(3, 8)
268 auto pair
= writeArchive(Dst
, Members
, WriteSymbtab
, Kind
, true, false);
270 auto pair
= writeArchive(Dst
, Members
, WriteSymbtab
, Kind
, true);
273 return LLVMRustResult::Success
;
274 LLVMRustSetLastError(pair
.second
.message().c_str());
275 return LLVMRustResult::Failure
;