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