]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/llvm/mod.rs
Simplify SaveHandler trait
[rust.git] / src / librustc_codegen_llvm / llvm / mod.rs
1 #![allow(non_upper_case_globals)]
2 #![allow(non_camel_case_types)]
3 #![allow(non_snake_case)]
4 #![deny(bare_trait_objects)]
5
6 pub use self::IntPredicate::*;
7 pub use self::RealPredicate::*;
8 pub use self::AtomicRmwBinOp::*;
9 pub use self::MetadataType::*;
10 pub use self::CodeGenOptSize::*;
11 pub use self::CallConv::*;
12 pub use self::Linkage::*;
13
14 use std::str::FromStr;
15 use std::string::FromUtf8Error;
16 use std::slice;
17 use std::ffi::CStr;
18 use std::cell::RefCell;
19 use libc::{c_uint, c_char, size_t};
20 use rustc_data_structures::small_c_str::SmallCStr;
21
22 pub mod archive_ro;
23 pub mod diagnostic;
24 mod ffi;
25
26 pub use self::ffi::*;
27
28 impl LLVMRustResult {
29     pub fn into_result(self) -> Result<(), ()> {
30         match self {
31             LLVMRustResult::Success => Ok(()),
32             LLVMRustResult::Failure => Err(()),
33         }
34     }
35 }
36
37 pub fn AddFunctionAttrStringValue(llfn: &'a Value,
38                                   idx: AttributePlace,
39                                   attr: &CStr,
40                                   value: &CStr) {
41     unsafe {
42         LLVMRustAddFunctionAttrStringValue(llfn,
43                                            idx.as_uint(),
44                                            attr.as_ptr(),
45                                            value.as_ptr())
46     }
47 }
48
49 #[derive(Copy, Clone)]
50 pub enum AttributePlace {
51     ReturnValue,
52     Argument(u32),
53     Function,
54 }
55
56 impl AttributePlace {
57     pub fn as_uint(self) -> c_uint {
58         match self {
59             AttributePlace::ReturnValue => 0,
60             AttributePlace::Argument(i) => 1 + i,
61             AttributePlace::Function => !0,
62         }
63     }
64 }
65
66 #[derive(Copy, Clone, PartialEq)]
67 #[repr(C)]
68 pub enum CodeGenOptSize {
69     CodeGenOptSizeNone = 0,
70     CodeGenOptSizeDefault = 1,
71     CodeGenOptSizeAggressive = 2,
72 }
73
74 impl FromStr for ArchiveKind {
75     type Err = ();
76
77     fn from_str(s: &str) -> Result<Self, Self::Err> {
78         match s {
79             "gnu" => Ok(ArchiveKind::K_GNU),
80             "bsd" => Ok(ArchiveKind::K_BSD),
81             "coff" => Ok(ArchiveKind::K_COFF),
82             _ => Err(()),
83         }
84     }
85 }
86
87 #[repr(C)]
88 pub struct RustString {
89     bytes: RefCell<Vec<u8>>,
90 }
91
92 /// Appending to a Rust string -- used by RawRustStringOstream.
93 #[no_mangle]
94 pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
95                                                  ptr: *const c_char,
96                                                  size: size_t) {
97     let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
98
99     sr.bytes.borrow_mut().extend_from_slice(slice);
100 }
101
102 pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
103     unsafe {
104         LLVMSetInstructionCallConv(instr, cc as c_uint);
105     }
106 }
107 pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
108     unsafe {
109         LLVMSetFunctionCallConv(fn_, cc as c_uint);
110     }
111 }
112
113 // Externally visible symbols that might appear in multiple codegen units need to appear in
114 // their own comdat section so that the duplicates can be discarded at link time. This can for
115 // example happen for generics when using multiple codegen units. This function simply uses the
116 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
117 // function.
118 // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
119 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
120     unsafe {
121         LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
122     }
123 }
124
125 pub fn UnsetComdat(val: &'a Value) {
126     unsafe {
127         LLVMRustUnsetComdat(val);
128     }
129 }
130
131 pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
132     unsafe {
133         LLVMSetUnnamedAddr(global, unnamed as Bool);
134     }
135 }
136
137 pub fn set_thread_local(global: &'a Value, is_thread_local: bool) {
138     unsafe {
139         LLVMSetThreadLocal(global, is_thread_local as Bool);
140     }
141 }
142 pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
143     unsafe {
144         LLVMSetThreadLocalMode(global, mode);
145     }
146 }
147
148 impl Attribute {
149     pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
150         unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
151     }
152
153     pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
154         unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
155     }
156
157     pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
158         unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
159     }
160
161     pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
162         if set {
163             self.apply_llfn(idx, llfn);
164         } else {
165             self.unapply_llfn(idx, llfn);
166         }
167     }
168 }
169
170 // Memory-managed interface to object files.
171
172 pub struct ObjectFile {
173     pub llof: &'static mut ffi::ObjectFile,
174 }
175
176 unsafe impl Send for ObjectFile {}
177
178 impl ObjectFile {
179     // This will take ownership of llmb
180     pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
181         unsafe {
182             let llof = LLVMCreateObjectFile(llmb)?;
183             Some(ObjectFile { llof })
184         }
185     }
186 }
187
188 impl Drop for ObjectFile {
189     fn drop(&mut self) {
190         unsafe {
191             LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
192         }
193     }
194 }
195
196 // Memory-managed interface to section iterators.
197
198 pub struct SectionIter<'a> {
199     pub llsi: &'a mut SectionIterator<'a>,
200 }
201
202 impl Drop for SectionIter<'a> {
203     fn drop(&mut self) {
204         unsafe {
205             LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
206         }
207     }
208 }
209
210 pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
211     unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
212 }
213
214 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
215 pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
216     unsafe {
217         assert!(index < LLVMCountParams(llfn),
218             "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
219         LLVMGetParam(llfn, index)
220     }
221 }
222
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 }