]> git.proxmox.com Git - rustc.git/blob - src/rustllvm/ArchiveWrapper.cpp
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / rustllvm / ArchiveWrapper.cpp
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.
4 //
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.
10
11 #include "rustllvm.h"
12
13 #include "llvm/Object/Archive.h"
14
15 #if LLVM_VERSION_MINOR >= 7
16 #include "llvm/Object/ArchiveWriter.h"
17 #endif
18
19 using namespace llvm;
20 using namespace llvm::object;
21
22 struct LLVMRustArchiveMember {
23 const char *filename;
24 const char *name;
25 Archive::Child child;
26
27 LLVMRustArchiveMember(): filename(NULL), name(NULL), child(NULL, NULL) {}
28 ~LLVMRustArchiveMember() {}
29 };
30
31 #if LLVM_VERSION_MINOR >= 6
32 typedef OwningBinary<Archive> RustArchive;
33 #define GET_ARCHIVE(a) ((a)->getBinary())
34 #else
35 typedef Archive RustArchive;
36 #define GET_ARCHIVE(a) (a)
37 #endif
38
39 extern "C" void*
40 LLVMRustOpenArchive(char *path) {
41 ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
42 -1,
43 false);
44 if (!buf_or) {
45 LLVMRustSetLastError(buf_or.getError().message().c_str());
46 return nullptr;
47 }
48
49 #if LLVM_VERSION_MINOR >= 6
50 ErrorOr<std::unique_ptr<Archive>> archive_or =
51 Archive::create(buf_or.get()->getMemBufferRef());
52
53 if (!archive_or) {
54 LLVMRustSetLastError(archive_or.getError().message().c_str());
55 return nullptr;
56 }
57
58 OwningBinary<Archive> *ret = new OwningBinary<Archive>(
59 std::move(archive_or.get()), std::move(buf_or.get()));
60 #else
61 std::error_code err;
62 Archive *ret = new Archive(std::move(buf_or.get()), err);
63 if (err) {
64 LLVMRustSetLastError(err.message().c_str());
65 return nullptr;
66 }
67 #endif
68
69 return ret;
70 }
71
72 extern "C" void
73 LLVMRustDestroyArchive(RustArchive *ar) {
74 delete ar;
75 }
76
77 struct RustArchiveIterator {
78 Archive::child_iterator cur;
79 Archive::child_iterator end;
80 };
81
82 extern "C" RustArchiveIterator*
83 LLVMRustArchiveIteratorNew(RustArchive *ra) {
84 Archive *ar = GET_ARCHIVE(ra);
85 RustArchiveIterator *rai = new RustArchiveIterator();
86 rai->cur = ar->child_begin();
87 rai->end = ar->child_end();
88 return rai;
89 }
90
91 extern "C" const Archive::Child*
92 LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
93 if (rai->cur == rai->end)
94 return NULL;
95 const Archive::Child *cur = rai->cur.operator->();
96 Archive::Child *ret = new Archive::Child(*cur);
97 ++rai->cur;
98 return ret;
99 }
100
101 extern "C" void
102 LLVMRustArchiveChildFree(Archive::Child *child) {
103 delete child;
104 }
105
106 extern "C" void
107 LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
108 delete rai;
109 }
110
111 extern "C" const char*
112 LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
113 ErrorOr<StringRef> name_or_err = child->getName();
114 if (name_or_err.getError())
115 return NULL;
116 StringRef name = name_or_err.get();
117 *size = name.size();
118 return name.data();
119 }
120
121 extern "C" const char*
122 LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
123 StringRef buf;
124 #if LLVM_VERSION_MINOR >= 7
125 ErrorOr<StringRef> buf_or_err = child->getBuffer();
126 if (buf_or_err.getError()) {
127 LLVMRustSetLastError(buf_or_err.getError().message().c_str());
128 return NULL;
129 }
130 buf = buf_or_err.get();
131 #else
132 buf = child->getBuffer();
133 #endif
134 *size = buf.size();
135 return buf.data();
136 }
137
138 extern "C" LLVMRustArchiveMember*
139 LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
140 LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
141 Member->filename = Filename;
142 Member->name = Name;
143 if (child)
144 Member->child = *child;
145 return Member;
146 }
147
148 extern "C" void
149 LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
150 delete Member;
151 }
152
153 extern "C" int
154 LLVMRustWriteArchive(char *Dst,
155 size_t NumMembers,
156 const LLVMRustArchiveMember **NewMembers,
157 bool WriteSymbtab,
158 Archive::Kind Kind) {
159 #if LLVM_VERSION_MINOR >= 7
160 std::vector<NewArchiveIterator> Members;
161
162 for (size_t i = 0; i < NumMembers; i++) {
163 auto Member = NewMembers[i];
164 assert(Member->name);
165 if (Member->filename) {
166 Members.push_back(NewArchiveIterator(Member->filename, Member->name));
167 } else {
168 Members.push_back(NewArchiveIterator(Member->child, Member->name));
169 }
170 }
171 auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
172 if (!pair.second)
173 return 0;
174 LLVMRustSetLastError(pair.second.message().c_str());
175 #else
176 LLVMRustSetLastError("writing archives not supported with this LLVM version");
177 #endif
178 return -1;
179 }