]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/llvm/mod.rs
Rollup merge of #67094 - RalfJung:fields, r=Mark-Simulacrum
[rust.git] / src / librustc_codegen_llvm / llvm / mod.rs
1 #![allow(non_snake_case)]
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;
13 use std::slice;
14 use std::ffi::CStr;
15 use std::cell::RefCell;
16 use libc::{c_uint, c_char, size_t};
17 use rustc_data_structures::small_c_str::SmallCStr;
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
84 #[repr(C)]
85 pub struct RustString {
86     bytes: RefCell<Vec<u8>>,
87 }
88
89 /// Appending to a Rust string -- used by RawRustStringOstream.
90 #[no_mangle]
91 pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString,
92                                                  ptr: *const c_char,
93                                                  size: size_t) {
94     let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
95
96     sr.bytes.borrow_mut().extend_from_slice(slice);
97 }
98
99 pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) {
100     unsafe {
101         LLVMSetInstructionCallConv(instr, cc as c_uint);
102     }
103 }
104 pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) {
105     unsafe {
106         LLVMSetFunctionCallConv(fn_, cc as c_uint);
107     }
108 }
109
110 // Externally visible symbols that might appear in multiple codegen units need to appear in
111 // their own comdat section so that the duplicates can be discarded at link time. This can for
112 // example happen for generics when using multiple codegen units. This function simply uses the
113 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
114 // function.
115 // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52
116 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) {
117     unsafe {
118         let name = get_value_name(val);
119         LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len());
120     }
121 }
122
123 pub fn UnsetComdat(val: &'a Value) {
124     unsafe {
125         LLVMRustUnsetComdat(val);
126     }
127 }
128
129 pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) {
130     unsafe {
131         LLVMSetUnnamedAddr(global, unnamed as Bool);
132     }
133 }
134
135 pub fn set_thread_local(global: &'a Value, is_thread_local: bool) {
136     unsafe {
137         LLVMSetThreadLocal(global, is_thread_local as Bool);
138     }
139 }
140 pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) {
141     unsafe {
142         LLVMSetThreadLocalMode(global, mode);
143     }
144 }
145
146 impl Attribute {
147     pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) {
148         unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
149     }
150
151     pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
152         unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
153     }
154
155     pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) {
156         unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
157     }
158
159     pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
160         if set {
161             self.apply_llfn(idx, llfn);
162         } else {
163             self.unapply_llfn(idx, llfn);
164         }
165     }
166 }
167
168 // Memory-managed interface to object files.
169
170 pub struct ObjectFile {
171     pub llof: &'static mut ffi::ObjectFile,
172 }
173
174 unsafe impl Send for ObjectFile {}
175
176 impl ObjectFile {
177     // This will take ownership of llmb
178     pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
179         unsafe {
180             let llof = LLVMCreateObjectFile(llmb)?;
181             Some(ObjectFile { llof })
182         }
183     }
184 }
185
186 impl Drop for ObjectFile {
187     fn drop(&mut self) {
188         unsafe {
189             LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
190         }
191     }
192 }
193
194 // Memory-managed interface to section iterators.
195
196 pub struct SectionIter<'a> {
197     pub llsi: &'a mut SectionIterator<'a>,
198 }
199
200 impl Drop for SectionIter<'a> {
201     fn drop(&mut self) {
202         unsafe {
203             LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
204         }
205     }
206 }
207
208 pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> {
209     unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
210 }
211
212 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
213 pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value {
214     unsafe {
215         assert!(index < LLVMCountParams(llfn),
216             "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
217         LLVMGetParam(llfn, index)
218     }
219 }
220
221 /// Safe wrapper for `LLVMGetValueName2` into a byte slice
222 pub fn get_value_name(value: &'a Value) -> &'a [u8] {
223     unsafe {
224         let mut len = 0;
225         let data = LLVMGetValueName2(value, &mut len);
226         std::slice::from_raw_parts(data.cast(), len)
227     }
228 }
229
230 /// Safe wrapper for `LLVMSetValueName2` from a byte slice
231 pub fn set_value_name(value: &Value, name: &[u8]) {
232     unsafe {
233         let data = name.as_ptr().cast();
234         LLVMSetValueName2(value, data, name.len());
235     }
236 }
237
238 pub fn build_string(f: impl FnOnce(&RustString)) -> Result<String, FromUtf8Error> {
239     let sr = RustString {
240         bytes: RefCell::new(Vec::new()),
241     };
242     f(&sr);
243     String::from_utf8(sr.bytes.into_inner())
244 }
245
246 pub fn twine_to_string(tr: &Twine) -> String {
247     unsafe {
248         build_string(|s| LLVMRustWriteTwineToString(tr, s))
249             .expect("got a non-UTF8 Twine from LLVM")
250     }
251 }
252
253 pub fn last_error() -> Option<String> {
254     unsafe {
255         let cstr = LLVMRustGetLastError();
256         if cstr.is_null() {
257             None
258         } else {
259             let err = CStr::from_ptr(cstr).to_bytes();
260             let err = String::from_utf8_lossy(err).to_string();
261             libc::free(cstr as *mut _);
262             Some(err)
263         }
264     }
265 }
266
267 pub struct OperandBundleDef<'a> {
268     pub raw: &'a mut ffi::OperandBundleDef<'a>,
269 }
270
271 impl OperandBundleDef<'a> {
272     pub fn new(name: &str, vals: &[&'a Value]) -> Self {
273         let name = SmallCStr::new(name);
274         let def = unsafe {
275             LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
276         };
277         OperandBundleDef { raw: def }
278     }
279 }
280
281 impl Drop for OperandBundleDef<'a> {
282     fn drop(&mut self) {
283         unsafe {
284             LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _));
285         }
286     }
287 }