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