]> git.lizzy.rs Git - rust.git/blob - src/librustc_llvm/lib.rs
Auto merge of #41433 - estebank:constructor, r=michaelwoerister
[rust.git] / src / librustc_llvm / lib.rs
1 // Copyright 2012-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 #![allow(non_upper_case_globals)]
12 #![allow(non_camel_case_types)]
13 #![allow(non_snake_case)]
14 #![allow(dead_code)]
15
16 #![crate_name = "rustc_llvm"]
17 #![unstable(feature = "rustc_private", issue = "27812")]
18 #![crate_type = "dylib"]
19 #![crate_type = "rlib"]
20 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
21        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
22        html_root_url = "https://doc.rust-lang.org/nightly/")]
23 #![deny(warnings)]
24
25 #![feature(associated_consts)]
26 #![feature(box_syntax)]
27 #![feature(concat_idents)]
28 #![feature(libc)]
29 #![feature(link_args)]
30 #![feature(staged_api)]
31 #![feature(rustc_private)]
32 #![feature(static_nobundle)]
33
34 extern crate libc;
35 #[macro_use]
36 #[no_link]
37 extern crate rustc_bitflags;
38
39 pub use self::IntPredicate::*;
40 pub use self::RealPredicate::*;
41 pub use self::TypeKind::*;
42 pub use self::AtomicRmwBinOp::*;
43 pub use self::MetadataType::*;
44 pub use self::CodeGenOptSize::*;
45 pub use self::DiagnosticKind::*;
46 pub use self::CallConv::*;
47 pub use self::DiagnosticSeverity::*;
48 pub use self::Linkage::*;
49
50 use std::str::FromStr;
51 use std::slice;
52 use std::ffi::{CString, CStr};
53 use std::cell::RefCell;
54 use libc::{c_uint, c_char, size_t};
55
56 pub mod archive_ro;
57 pub mod diagnostic;
58 pub mod ffi;
59
60 pub use ffi::*;
61
62 impl LLVMRustResult {
63     pub fn into_result(self) -> Result<(), ()> {
64         match self {
65             LLVMRustResult::Success => Ok(()),
66             LLVMRustResult::Failure => Err(()),
67         }
68     }
69 }
70
71 pub fn AddFunctionAttrStringValue(llfn: ValueRef,
72                                   idx: AttributePlace,
73                                   attr: &CStr,
74                                   value: &CStr) {
75     unsafe {
76         LLVMRustAddFunctionAttrStringValue(llfn,
77                                            idx.as_uint(),
78                                            attr.as_ptr(),
79                                            value.as_ptr())
80     }
81 }
82
83 #[repr(C)]
84 #[derive(Copy, Clone)]
85 pub enum AttributePlace {
86     Argument(u32),
87     Function,
88 }
89
90 impl AttributePlace {
91     pub fn ReturnValue() -> Self {
92         AttributePlace::Argument(0)
93     }
94
95     pub fn as_uint(self) -> c_uint {
96         match self {
97             AttributePlace::Function => !0,
98             AttributePlace::Argument(i) => i,
99         }
100     }
101 }
102
103 #[derive(Copy, Clone, PartialEq)]
104 #[repr(C)]
105 pub enum CodeGenOptSize {
106     CodeGenOptSizeNone = 0,
107     CodeGenOptSizeDefault = 1,
108     CodeGenOptSizeAggressive = 2,
109 }
110
111 impl FromStr for ArchiveKind {
112     type Err = ();
113
114     fn from_str(s: &str) -> Result<Self, Self::Err> {
115         match s {
116             "gnu" => Ok(ArchiveKind::K_GNU),
117             "mips64" => Ok(ArchiveKind::K_MIPS64),
118             "bsd" => Ok(ArchiveKind::K_BSD),
119             "coff" => Ok(ArchiveKind::K_COFF),
120             _ => Err(()),
121         }
122     }
123 }
124
125 #[allow(missing_copy_implementations)]
126 pub enum RustString_opaque {}
127 pub type RustStringRef = *mut RustString_opaque;
128 type RustStringRepr = *mut RefCell<Vec<u8>>;
129
130 /// Appending to a Rust string -- used by RawRustStringOstream.
131 #[no_mangle]
132 pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
133                                                  ptr: *const c_char,
134                                                  size: size_t) {
135     let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
136
137     let sr = sr as RustStringRepr;
138     (*sr).borrow_mut().extend_from_slice(slice);
139 }
140
141 pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
142     unsafe {
143         LLVMSetInstructionCallConv(instr, cc as c_uint);
144     }
145 }
146 pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
147     unsafe {
148         LLVMSetFunctionCallConv(fn_, cc as c_uint);
149     }
150 }
151
152 // Externally visible symbols that might appear in multiple translation units need to appear in
153 // their own comdat section so that the duplicates can be discarded at link time. This can for
154 // example happen for generics when using multiple codegen units. This function simply uses the
155 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
156 // function.
157 // For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
158 pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
159     unsafe {
160         LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
161     }
162 }
163
164 pub fn UnsetComdat(val: ValueRef) {
165     unsafe {
166         LLVMRustUnsetComdat(val);
167     }
168 }
169
170 pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
171     unsafe {
172         LLVMSetUnnamedAddr(global, unnamed as Bool);
173     }
174 }
175
176 pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
177     unsafe {
178         LLVMSetThreadLocal(global, is_thread_local as Bool);
179     }
180 }
181
182 impl Attribute {
183     pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
184         unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
185     }
186
187     pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
188         unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
189     }
190
191     pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
192         unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
193     }
194
195     pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
196         if set {
197             self.apply_llfn(idx, llfn);
198         } else {
199             self.unapply_llfn(idx, llfn);
200         }
201     }
202 }
203
204 // Memory-managed interface to target data.
205
206 pub struct TargetData {
207     pub lltd: TargetDataRef,
208 }
209
210 impl Drop for TargetData {
211     fn drop(&mut self) {
212         unsafe {
213             LLVMDisposeTargetData(self.lltd);
214         }
215     }
216 }
217
218 pub fn mk_target_data(string_rep: &str) -> TargetData {
219     let string_rep = CString::new(string_rep).unwrap();
220     TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
221 }
222
223 // Memory-managed interface to object files.
224
225 pub struct ObjectFile {
226     pub llof: ObjectFileRef,
227 }
228
229 impl ObjectFile {
230     // This will take ownership of llmb
231     pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
232         unsafe {
233             let llof = LLVMCreateObjectFile(llmb);
234             if llof as isize == 0 {
235                 // LLVMCreateObjectFile took ownership of llmb
236                 return None;
237             }
238
239             Some(ObjectFile { llof: llof })
240         }
241     }
242 }
243
244 impl Drop for ObjectFile {
245     fn drop(&mut self) {
246         unsafe {
247             LLVMDisposeObjectFile(self.llof);
248         }
249     }
250 }
251
252 // Memory-managed interface to section iterators.
253
254 pub struct SectionIter {
255     pub llsi: SectionIteratorRef,
256 }
257
258 impl Drop for SectionIter {
259     fn drop(&mut self) {
260         unsafe {
261             LLVMDisposeSectionIterator(self.llsi);
262         }
263     }
264 }
265
266 pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
267     unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
268 }
269
270 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
271 pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
272     unsafe {
273         assert!(index < LLVMCountParams(llfn),
274             "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
275         LLVMGetParam(llfn, index)
276     }
277 }
278
279 pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
280     unsafe {
281         let num_params = LLVMCountParams(llfn);
282         let mut params = Vec::with_capacity(num_params as usize);
283         for idx in 0..num_params {
284             params.push(LLVMGetParam(llfn, idx));
285         }
286
287         params
288     }
289 }
290
291 pub fn build_string<F>(f: F) -> Option<String>
292     where F: FnOnce(RustStringRef)
293 {
294     let mut buf = RefCell::new(Vec::new());
295     f(&mut buf as RustStringRepr as RustStringRef);
296     String::from_utf8(buf.into_inner()).ok()
297 }
298
299 pub unsafe fn twine_to_string(tr: TwineRef) -> String {
300     build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
301 }
302
303 pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
304     build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
305         .expect("got a non-UTF8 DebugLoc from LLVM")
306 }
307
308 pub fn initialize_available_targets() {
309     macro_rules! init_target(
310         ($cfg:meta, $($method:ident),*) => { {
311             #[cfg($cfg)]
312             fn init() {
313                 extern {
314                     $(fn $method();)*
315                 }
316                 unsafe {
317                     $($method();)*
318                 }
319             }
320             #[cfg(not($cfg))]
321             fn init() { }
322             init();
323         } }
324     );
325     init_target!(llvm_component = "x86",
326                  LLVMInitializeX86TargetInfo,
327                  LLVMInitializeX86Target,
328                  LLVMInitializeX86TargetMC,
329                  LLVMInitializeX86AsmPrinter,
330                  LLVMInitializeX86AsmParser);
331     init_target!(llvm_component = "arm",
332                  LLVMInitializeARMTargetInfo,
333                  LLVMInitializeARMTarget,
334                  LLVMInitializeARMTargetMC,
335                  LLVMInitializeARMAsmPrinter,
336                  LLVMInitializeARMAsmParser);
337     init_target!(llvm_component = "aarch64",
338                  LLVMInitializeAArch64TargetInfo,
339                  LLVMInitializeAArch64Target,
340                  LLVMInitializeAArch64TargetMC,
341                  LLVMInitializeAArch64AsmPrinter,
342                  LLVMInitializeAArch64AsmParser);
343     init_target!(llvm_component = "mips",
344                  LLVMInitializeMipsTargetInfo,
345                  LLVMInitializeMipsTarget,
346                  LLVMInitializeMipsTargetMC,
347                  LLVMInitializeMipsAsmPrinter,
348                  LLVMInitializeMipsAsmParser);
349     init_target!(llvm_component = "powerpc",
350                  LLVMInitializePowerPCTargetInfo,
351                  LLVMInitializePowerPCTarget,
352                  LLVMInitializePowerPCTargetMC,
353                  LLVMInitializePowerPCAsmPrinter,
354                  LLVMInitializePowerPCAsmParser);
355     init_target!(llvm_component = "pnacl",
356                  LLVMInitializePNaClTargetInfo,
357                  LLVMInitializePNaClTarget,
358                  LLVMInitializePNaClTargetMC);
359     init_target!(llvm_component = "systemz",
360                  LLVMInitializeSystemZTargetInfo,
361                  LLVMInitializeSystemZTarget,
362                  LLVMInitializeSystemZTargetMC,
363                  LLVMInitializeSystemZAsmPrinter,
364                  LLVMInitializeSystemZAsmParser);
365     init_target!(llvm_component = "jsbackend",
366                  LLVMInitializeJSBackendTargetInfo,
367                  LLVMInitializeJSBackendTarget,
368                  LLVMInitializeJSBackendTargetMC);
369     init_target!(llvm_component = "msp430",
370                  LLVMInitializeMSP430TargetInfo,
371                  LLVMInitializeMSP430Target,
372                  LLVMInitializeMSP430TargetMC,
373                  LLVMInitializeMSP430AsmPrinter);
374     init_target!(llvm_component = "sparc",
375                  LLVMInitializeSparcTargetInfo,
376                  LLVMInitializeSparcTarget,
377                  LLVMInitializeSparcTargetMC,
378                  LLVMInitializeSparcAsmPrinter,
379                  LLVMInitializeSparcAsmParser);
380     init_target!(llvm_component = "nvptx",
381                  LLVMInitializeNVPTXTargetInfo,
382                  LLVMInitializeNVPTXTarget,
383                  LLVMInitializeNVPTXTargetMC,
384                  LLVMInitializeNVPTXAsmPrinter);
385     init_target!(llvm_component = "hexagon",
386                  LLVMInitializeHexagonTargetInfo,
387                  LLVMInitializeHexagonTarget,
388                  LLVMInitializeHexagonTargetMC,
389                  LLVMInitializeHexagonAsmPrinter,
390                  LLVMInitializeHexagonAsmParser);
391 }
392
393 pub fn last_error() -> Option<String> {
394     unsafe {
395         let cstr = LLVMRustGetLastError();
396         if cstr.is_null() {
397             None
398         } else {
399             let err = CStr::from_ptr(cstr).to_bytes();
400             let err = String::from_utf8_lossy(err).to_string();
401             libc::free(cstr as *mut _);
402             Some(err)
403         }
404     }
405 }
406
407 pub struct OperandBundleDef {
408     inner: OperandBundleDefRef,
409 }
410
411 impl OperandBundleDef {
412     pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
413         let name = CString::new(name).unwrap();
414         let def = unsafe {
415             LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
416         };
417         OperandBundleDef { inner: def }
418     }
419
420     pub fn raw(&self) -> OperandBundleDefRef {
421         self.inner
422     }
423 }
424
425 impl Drop for OperandBundleDef {
426     fn drop(&mut self) {
427         unsafe {
428             LLVMRustFreeOperandBundleDef(self.inner);
429         }
430     }
431 }