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