]> git.proxmox.com Git - rustc.git/blob - src/librustc_llvm/lib.rs
New upstream version 1.25.0+dfsg1
[rustc.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 "bsd" => Ok(ArchiveKind::K_BSD),
109 "coff" => Ok(ArchiveKind::K_COFF),
110 _ => Err(()),
111 }
112 }
113 }
114
115 #[allow(missing_copy_implementations)]
116 pub enum RustString_opaque {}
117 type RustStringRef = *mut RustString_opaque;
118 type RustStringRepr = *mut RefCell<Vec<u8>>;
119
120 /// Appending to a Rust string -- used by RawRustStringOstream.
121 #[no_mangle]
122 pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
123 ptr: *const c_char,
124 size: size_t) {
125 let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
126
127 let sr = sr as RustStringRepr;
128 (*sr).borrow_mut().extend_from_slice(slice);
129 }
130
131 pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
132 unsafe {
133 LLVMSetInstructionCallConv(instr, cc as c_uint);
134 }
135 }
136 pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
137 unsafe {
138 LLVMSetFunctionCallConv(fn_, cc as c_uint);
139 }
140 }
141
142 // Externally visible symbols that might appear in multiple translation units need to appear in
143 // their own comdat section so that the duplicates can be discarded at link time. This can for
144 // example happen for generics when using multiple codegen units. This function simply uses the
145 // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
146 // function.
147 // For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
148 pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
149 unsafe {
150 LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
151 }
152 }
153
154 pub fn UnsetComdat(val: ValueRef) {
155 unsafe {
156 LLVMRustUnsetComdat(val);
157 }
158 }
159
160 pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
161 unsafe {
162 LLVMSetUnnamedAddr(global, unnamed as Bool);
163 }
164 }
165
166 pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
167 unsafe {
168 LLVMSetThreadLocal(global, is_thread_local as Bool);
169 }
170 }
171 pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
172 unsafe {
173 LLVMSetThreadLocalMode(global, mode);
174 }
175 }
176
177 impl Attribute {
178 pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
179 unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
180 }
181
182 pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
183 unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
184 }
185
186 pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
187 unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
188 }
189
190 pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
191 if set {
192 self.apply_llfn(idx, llfn);
193 } else {
194 self.unapply_llfn(idx, llfn);
195 }
196 }
197 }
198
199 // Memory-managed interface to target data.
200
201 struct TargetData {
202 lltd: TargetDataRef,
203 }
204
205 impl Drop for TargetData {
206 fn drop(&mut self) {
207 unsafe {
208 LLVMDisposeTargetData(self.lltd);
209 }
210 }
211 }
212
213 fn mk_target_data(string_rep: &str) -> TargetData {
214 let string_rep = CString::new(string_rep).unwrap();
215 TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
216 }
217
218 // Memory-managed interface to object files.
219
220 pub struct ObjectFile {
221 pub llof: ObjectFileRef,
222 }
223
224 impl ObjectFile {
225 // This will take ownership of llmb
226 pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
227 unsafe {
228 let llof = LLVMCreateObjectFile(llmb);
229 if llof as isize == 0 {
230 // LLVMCreateObjectFile took ownership of llmb
231 return None;
232 }
233
234 Some(ObjectFile { llof: llof })
235 }
236 }
237 }
238
239 impl Drop for ObjectFile {
240 fn drop(&mut self) {
241 unsafe {
242 LLVMDisposeObjectFile(self.llof);
243 }
244 }
245 }
246
247 // Memory-managed interface to section iterators.
248
249 pub struct SectionIter {
250 pub llsi: SectionIteratorRef,
251 }
252
253 impl Drop for SectionIter {
254 fn drop(&mut self) {
255 unsafe {
256 LLVMDisposeSectionIterator(self.llsi);
257 }
258 }
259 }
260
261 pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
262 unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
263 }
264
265 /// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
266 pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
267 unsafe {
268 assert!(index < LLVMCountParams(llfn),
269 "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
270 LLVMGetParam(llfn, index)
271 }
272 }
273
274 fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
275 unsafe {
276 let num_params = LLVMCountParams(llfn);
277 let mut params = Vec::with_capacity(num_params as usize);
278 for idx in 0..num_params {
279 params.push(LLVMGetParam(llfn, idx));
280 }
281
282 params
283 }
284 }
285
286 pub fn build_string<F>(f: F) -> Option<String>
287 where F: FnOnce(RustStringRef)
288 {
289 let mut buf = RefCell::new(Vec::new());
290 f(&mut buf as RustStringRepr as RustStringRef);
291 String::from_utf8(buf.into_inner()).ok()
292 }
293
294 pub unsafe fn twine_to_string(tr: TwineRef) -> String {
295 build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
296 }
297
298 pub fn initialize_available_targets() {
299 macro_rules! init_target(
300 ($cfg:meta, $($method:ident),*) => { {
301 #[cfg($cfg)]
302 fn init() {
303 extern {
304 $(fn $method();)*
305 }
306 unsafe {
307 $($method();)*
308 }
309 }
310 #[cfg(not($cfg))]
311 fn init() { }
312 init();
313 } }
314 );
315 init_target!(llvm_component = "x86",
316 LLVMInitializeX86TargetInfo,
317 LLVMInitializeX86Target,
318 LLVMInitializeX86TargetMC,
319 LLVMInitializeX86AsmPrinter,
320 LLVMInitializeX86AsmParser);
321 init_target!(llvm_component = "arm",
322 LLVMInitializeARMTargetInfo,
323 LLVMInitializeARMTarget,
324 LLVMInitializeARMTargetMC,
325 LLVMInitializeARMAsmPrinter,
326 LLVMInitializeARMAsmParser);
327 init_target!(llvm_component = "aarch64",
328 LLVMInitializeAArch64TargetInfo,
329 LLVMInitializeAArch64Target,
330 LLVMInitializeAArch64TargetMC,
331 LLVMInitializeAArch64AsmPrinter,
332 LLVMInitializeAArch64AsmParser);
333 init_target!(llvm_component = "mips",
334 LLVMInitializeMipsTargetInfo,
335 LLVMInitializeMipsTarget,
336 LLVMInitializeMipsTargetMC,
337 LLVMInitializeMipsAsmPrinter,
338 LLVMInitializeMipsAsmParser);
339 init_target!(llvm_component = "powerpc",
340 LLVMInitializePowerPCTargetInfo,
341 LLVMInitializePowerPCTarget,
342 LLVMInitializePowerPCTargetMC,
343 LLVMInitializePowerPCAsmPrinter,
344 LLVMInitializePowerPCAsmParser);
345 init_target!(llvm_component = "systemz",
346 LLVMInitializeSystemZTargetInfo,
347 LLVMInitializeSystemZTarget,
348 LLVMInitializeSystemZTargetMC,
349 LLVMInitializeSystemZAsmPrinter,
350 LLVMInitializeSystemZAsmParser);
351 init_target!(llvm_component = "jsbackend",
352 LLVMInitializeJSBackendTargetInfo,
353 LLVMInitializeJSBackendTarget,
354 LLVMInitializeJSBackendTargetMC);
355 init_target!(llvm_component = "msp430",
356 LLVMInitializeMSP430TargetInfo,
357 LLVMInitializeMSP430Target,
358 LLVMInitializeMSP430TargetMC,
359 LLVMInitializeMSP430AsmPrinter);
360 init_target!(llvm_component = "sparc",
361 LLVMInitializeSparcTargetInfo,
362 LLVMInitializeSparcTarget,
363 LLVMInitializeSparcTargetMC,
364 LLVMInitializeSparcAsmPrinter,
365 LLVMInitializeSparcAsmParser);
366 init_target!(llvm_component = "nvptx",
367 LLVMInitializeNVPTXTargetInfo,
368 LLVMInitializeNVPTXTarget,
369 LLVMInitializeNVPTXTargetMC,
370 LLVMInitializeNVPTXAsmPrinter);
371 init_target!(llvm_component = "hexagon",
372 LLVMInitializeHexagonTargetInfo,
373 LLVMInitializeHexagonTarget,
374 LLVMInitializeHexagonTargetMC,
375 LLVMInitializeHexagonAsmPrinter,
376 LLVMInitializeHexagonAsmParser);
377 init_target!(llvm_component = "webassembly",
378 LLVMInitializeWebAssemblyTargetInfo,
379 LLVMInitializeWebAssemblyTarget,
380 LLVMInitializeWebAssemblyTargetMC,
381 LLVMInitializeWebAssemblyAsmPrinter);
382 }
383
384 pub fn last_error() -> Option<String> {
385 unsafe {
386 let cstr = LLVMRustGetLastError();
387 if cstr.is_null() {
388 None
389 } else {
390 let err = CStr::from_ptr(cstr).to_bytes();
391 let err = String::from_utf8_lossy(err).to_string();
392 libc::free(cstr as *mut _);
393 Some(err)
394 }
395 }
396 }
397
398 pub struct OperandBundleDef {
399 inner: OperandBundleDefRef,
400 }
401
402 impl OperandBundleDef {
403 pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
404 let name = CString::new(name).unwrap();
405 let def = unsafe {
406 LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
407 };
408 OperandBundleDef { inner: def }
409 }
410
411 pub fn raw(&self) -> OperandBundleDefRef {
412 self.inner
413 }
414 }
415
416 impl Drop for OperandBundleDef {
417 fn drop(&mut self) {
418 unsafe {
419 LLVMRustFreeOperandBundleDef(self.inner);
420 }
421 }
422 }