]>
Commit | Line | Data |
---|---|---|
b7449926 | 1 | #![allow(non_snake_case)] |
b7449926 XL |
2 | |
3 | pub use self::IntPredicate::*; | |
4 | pub use self::RealPredicate::*; | |
5 | pub use self::AtomicRmwBinOp::*; | |
6 | pub use self::MetadataType::*; | |
7 | pub use self::CodeGenOptSize::*; | |
8 | pub use self::CallConv::*; | |
9 | pub use self::Linkage::*; | |
10 | ||
11 | use std::str::FromStr; | |
12 | use std::string::FromUtf8Error; | |
b7449926 XL |
13 | use std::ffi::CStr; |
14 | use std::cell::RefCell; | |
60c5eb7d | 15 | use libc::c_uint; |
b7449926 | 16 | use rustc_data_structures::small_c_str::SmallCStr; |
60c5eb7d | 17 | use rustc_llvm::RustString; |
b7449926 XL |
18 | |
19 | pub mod archive_ro; | |
20 | pub mod diagnostic; | |
21 | mod ffi; | |
22 | ||
23 | pub use self::ffi::*; | |
24 | ||
25 | impl LLVMRustResult { | |
26 | pub fn into_result(self) -> Result<(), ()> { | |
27 | match self { | |
28 | LLVMRustResult::Success => Ok(()), | |
29 | LLVMRustResult::Failure => Err(()), | |
30 | } | |
31 | } | |
32 | } | |
33 | ||
34 | pub fn AddFunctionAttrStringValue(llfn: &'a Value, | |
35 | idx: AttributePlace, | |
36 | attr: &CStr, | |
37 | value: &CStr) { | |
38 | unsafe { | |
39 | LLVMRustAddFunctionAttrStringValue(llfn, | |
40 | idx.as_uint(), | |
41 | attr.as_ptr(), | |
42 | value.as_ptr()) | |
43 | } | |
44 | } | |
45 | ||
46 | #[derive(Copy, Clone)] | |
47 | pub enum AttributePlace { | |
48 | ReturnValue, | |
49 | Argument(u32), | |
50 | Function, | |
51 | } | |
52 | ||
53 | impl AttributePlace { | |
54 | pub fn as_uint(self) -> c_uint { | |
55 | match self { | |
56 | AttributePlace::ReturnValue => 0, | |
57 | AttributePlace::Argument(i) => 1 + i, | |
58 | AttributePlace::Function => !0, | |
59 | } | |
60 | } | |
61 | } | |
62 | ||
63 | #[derive(Copy, Clone, PartialEq)] | |
64 | #[repr(C)] | |
65 | pub enum CodeGenOptSize { | |
66 | CodeGenOptSizeNone = 0, | |
67 | CodeGenOptSizeDefault = 1, | |
68 | CodeGenOptSizeAggressive = 2, | |
69 | } | |
70 | ||
71 | impl FromStr for ArchiveKind { | |
72 | type Err = (); | |
73 | ||
74 | fn from_str(s: &str) -> Result<Self, Self::Err> { | |
75 | match s { | |
76 | "gnu" => Ok(ArchiveKind::K_GNU), | |
77 | "bsd" => Ok(ArchiveKind::K_BSD), | |
78 | "coff" => Ok(ArchiveKind::K_COFF), | |
79 | _ => Err(()), | |
80 | } | |
81 | } | |
82 | } | |
83 | ||
b7449926 XL |
84 | pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { |
85 | unsafe { | |
86 | LLVMSetInstructionCallConv(instr, cc as c_uint); | |
87 | } | |
88 | } | |
89 | pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { | |
90 | unsafe { | |
91 | LLVMSetFunctionCallConv(fn_, cc as c_uint); | |
92 | } | |
93 | } | |
94 | ||
95 | // Externally visible symbols that might appear in multiple codegen units need to appear in | |
96 | // their own comdat section so that the duplicates can be discarded at link time. This can for | |
97 | // example happen for generics when using multiple codegen units. This function simply uses the | |
98 | // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the | |
99 | // function. | |
0731742a | 100 | // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52 |
b7449926 XL |
101 | pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { |
102 | unsafe { | |
60c5eb7d XL |
103 | let name = get_value_name(val); |
104 | LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); | |
b7449926 XL |
105 | } |
106 | } | |
107 | ||
108 | pub fn UnsetComdat(val: &'a Value) { | |
109 | unsafe { | |
110 | LLVMRustUnsetComdat(val); | |
111 | } | |
112 | } | |
113 | ||
114 | pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) { | |
115 | unsafe { | |
116 | LLVMSetUnnamedAddr(global, unnamed as Bool); | |
117 | } | |
118 | } | |
119 | ||
120 | pub fn set_thread_local(global: &'a Value, is_thread_local: bool) { | |
121 | unsafe { | |
122 | LLVMSetThreadLocal(global, is_thread_local as Bool); | |
123 | } | |
124 | } | |
125 | pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) { | |
126 | unsafe { | |
127 | LLVMSetThreadLocalMode(global, mode); | |
128 | } | |
129 | } | |
130 | ||
131 | impl Attribute { | |
132 | pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { | |
133 | unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } | |
134 | } | |
135 | ||
136 | pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { | |
137 | unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } | |
138 | } | |
139 | ||
140 | pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) { | |
141 | unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } | |
142 | } | |
143 | ||
144 | pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) { | |
145 | if set { | |
146 | self.apply_llfn(idx, llfn); | |
147 | } else { | |
148 | self.unapply_llfn(idx, llfn); | |
149 | } | |
150 | } | |
151 | } | |
152 | ||
153 | // Memory-managed interface to object files. | |
154 | ||
155 | pub struct ObjectFile { | |
156 | pub llof: &'static mut ffi::ObjectFile, | |
157 | } | |
158 | ||
159 | unsafe impl Send for ObjectFile {} | |
160 | ||
161 | impl ObjectFile { | |
162 | // This will take ownership of llmb | |
163 | pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> { | |
164 | unsafe { | |
165 | let llof = LLVMCreateObjectFile(llmb)?; | |
a1dfa0c6 | 166 | Some(ObjectFile { llof }) |
b7449926 XL |
167 | } |
168 | } | |
169 | } | |
170 | ||
171 | impl Drop for ObjectFile { | |
172 | fn drop(&mut self) { | |
173 | unsafe { | |
174 | LLVMDisposeObjectFile(&mut *(self.llof as *mut _)); | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
179 | // Memory-managed interface to section iterators. | |
180 | ||
181 | pub struct SectionIter<'a> { | |
182 | pub llsi: &'a mut SectionIterator<'a>, | |
183 | } | |
184 | ||
185 | impl Drop for SectionIter<'a> { | |
186 | fn drop(&mut self) { | |
187 | unsafe { | |
188 | LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _)); | |
189 | } | |
190 | } | |
191 | } | |
192 | ||
193 | pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> { | |
194 | unsafe { SectionIter { llsi: LLVMGetSections(llof) } } | |
195 | } | |
196 | ||
197 | /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. | |
198 | pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { | |
199 | unsafe { | |
200 | assert!(index < LLVMCountParams(llfn), | |
201 | "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn)); | |
202 | LLVMGetParam(llfn, index) | |
203 | } | |
204 | } | |
205 | ||
60c5eb7d XL |
206 | /// Safe wrapper for `LLVMGetValueName2` into a byte slice |
207 | pub fn get_value_name(value: &'a Value) -> &'a [u8] { | |
208 | unsafe { | |
209 | let mut len = 0; | |
210 | let data = LLVMGetValueName2(value, &mut len); | |
211 | std::slice::from_raw_parts(data.cast(), len) | |
212 | } | |
213 | } | |
214 | ||
215 | /// Safe wrapper for `LLVMSetValueName2` from a byte slice | |
216 | pub fn set_value_name(value: &Value, name: &[u8]) { | |
217 | unsafe { | |
218 | let data = name.as_ptr().cast(); | |
219 | LLVMSetValueName2(value, data, name.len()); | |
220 | } | |
221 | } | |
222 | ||
b7449926 XL |
223 | pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> { |
224 | let sr = RustString { | |
225 | bytes: RefCell::new(Vec::new()), | |
226 | }; | |
227 | f(&sr); | |
228 | String::from_utf8(sr.bytes.into_inner()) | |
229 | } | |
230 | ||
231 | pub fn twine_to_string(tr: &Twine) -> String { | |
232 | unsafe { | |
233 | build_string(|s| LLVMRustWriteTwineToString(tr, s)) | |
234 | .expect("got a non-UTF8 Twine from LLVM") | |
235 | } | |
236 | } | |
237 | ||
238 | pub fn last_error() -> Option<String> { | |
239 | unsafe { | |
240 | let cstr = LLVMRustGetLastError(); | |
241 | if cstr.is_null() { | |
242 | None | |
243 | } else { | |
244 | let err = CStr::from_ptr(cstr).to_bytes(); | |
245 | let err = String::from_utf8_lossy(err).to_string(); | |
246 | libc::free(cstr as *mut _); | |
247 | Some(err) | |
248 | } | |
249 | } | |
250 | } | |
251 | ||
252 | pub struct OperandBundleDef<'a> { | |
253 | pub raw: &'a mut ffi::OperandBundleDef<'a>, | |
254 | } | |
255 | ||
256 | impl OperandBundleDef<'a> { | |
257 | pub fn new(name: &str, vals: &[&'a Value]) -> Self { | |
258 | let name = SmallCStr::new(name); | |
259 | let def = unsafe { | |
260 | LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) | |
261 | }; | |
262 | OperandBundleDef { raw: def } | |
263 | } | |
264 | } | |
265 | ||
266 | impl Drop for OperandBundleDef<'a> { | |
267 | fn drop(&mut self) { | |
268 | unsafe { | |
269 | LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); | |
270 | } | |
271 | } | |
272 | } |