lib.rs 12.7 KB
Newer Older
A
Akos Kiss 已提交
1
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

A
Aaron Turon 已提交
11
#![allow(non_upper_case_globals)]
12
#![allow(non_camel_case_types)]
13
#![allow(non_snake_case)]
C
Corey Richardson 已提交
14
#![allow(dead_code)]
15

16
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
A
Alex Crichton 已提交
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)]
A
Alex Crichton 已提交
22
#![feature(concat_idents)]
23
#![feature(libc)]
A
Alex Crichton 已提交
24
#![feature(link_args)]
25
#![feature(static_nobundle)]
26

27 28 29 30
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)]
extern crate rustc_cratesio_shim;

31
#[macro_use]
32 33
extern crate bitflags;
extern crate libc;
34

S
Steven Fackler 已提交
35 36 37
pub use self::IntPredicate::*;
pub use self::RealPredicate::*;
pub use self::TypeKind::*;
38
pub use self::AtomicRmwBinOp::*;
S
Steven Fackler 已提交
39
pub use self::MetadataType::*;
40
pub use self::CodeGenOptSize::*;
S
Steven Fackler 已提交
41
pub use self::CallConv::*;
S
Steven Fackler 已提交
42
pub use self::Linkage::*;
S
Steven Fackler 已提交
43

J
Jake Goulding 已提交
44
use std::str::FromStr;
45
use std::slice;
A
Alex Crichton 已提交
46
use std::ffi::{CString, CStr};
47
use std::cell::RefCell;
A
Ariel Ben-Yehuda 已提交
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 57 58 59 60 61 62 63 64

impl LLVMRustResult {
    pub fn into_result(self) -> Result<(), ()> {
        match self {
            LLVMRustResult::Success => Ok(()),
            LLVMRustResult::Failure => Err(()),
        }
    }
}

65 66
pub fn AddFunctionAttrStringValue(llfn: ValueRef,
                                  idx: AttributePlace,
67 68
                                  attr: &CStr,
                                  value: &CStr) {
A
Ariel Ben-Yehuda 已提交
69
    unsafe {
70 71
        LLVMRustAddFunctionAttrStringValue(llfn,
                                           idx.as_uint(),
72 73
                                           attr.as_ptr(),
                                           value.as_ptr())
A
Ariel Ben-Yehuda 已提交
74 75 76
    }
}

77
#[derive(Copy, Clone)]
A
Ariel Ben-Yehuda 已提交
78
pub enum AttributePlace {
79
    ReturnValue,
A
Ariel Ben-Yehuda 已提交
80 81 82 83 84
    Argument(u32),
    Function,
}

impl AttributePlace {
85
    pub fn as_uint(self) -> c_uint {
A
Ariel Ben-Yehuda 已提交
86
        match self {
87 88
            AttributePlace::ReturnValue => 0,
            AttributePlace::Argument(i) => 1 + i,
A
Ariel Ben-Yehuda 已提交
89 90 91
            AttributePlace::Function => !0,
        }
    }
92 93
}

94 95 96 97 98 99 100 101
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CodeGenOptSize {
    CodeGenOptSizeNone = 0,
    CodeGenOptSizeDefault = 1,
    CodeGenOptSizeAggressive = 2,
}

J
Jake Goulding 已提交
102 103 104 105 106 107 108 109 110 111 112 113 114 115
impl FromStr for ArchiveKind {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "gnu" => Ok(ArchiveKind::K_GNU),
            "mips64" => Ok(ArchiveKind::K_MIPS64),
            "bsd" => Ok(ArchiveKind::K_BSD),
            "coff" => Ok(ArchiveKind::K_COFF),
            _ => Err(()),
        }
    }
}

116
#[allow(missing_copy_implementations)]
117
pub enum RustString_opaque {}
118
type RustStringRef = *mut RustString_opaque;
119
type RustStringRepr = *mut RefCell<Vec<u8>>;
120

I
Ian Kerins 已提交
121
/// Appending to a Rust string -- used by RawRustStringOstream.
122
#[no_mangle]
I
Ian Kerins 已提交
123 124 125
pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
                                                 ptr: *const c_char,
                                                 size: size_t) {
126
    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
127

128 129
    let sr = sr as RustStringRepr;
    (*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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
// Externally visible symbols that might appear in multiple translation units need to appear in
// their own comdat section so that the duplicates can be discarded at link time. This can for
// example happen for generics when using multiple codegen units. This function simply uses the
// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the
// function.
// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52
pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) {
    unsafe {
        LLVMRustSetComdat(llmod, val, LLVMGetValueName(val));
    }
}

pub fn UnsetComdat(val: ValueRef) {
    unsafe {
        LLVMRustUnsetComdat(val);
    }
}

161
pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
162
    unsafe {
163
        LLVMSetUnnamedAddr(global, unnamed as Bool);
164 165 166
    }
}

D
Daniel Micay 已提交
167 168
pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
    unsafe {
169
        LLVMSetThreadLocal(global, is_thread_local as Bool);
D
Daniel Micay 已提交
170 171
    }
}
172 173 174 175 176
pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) {
    unsafe {
        LLVMSetThreadLocalMode(global, mode);
    }
}
D
Daniel Micay 已提交
177

A
Ariel Ben-Yehuda 已提交
178 179
impl Attribute {
    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
180
        unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
C
Corey Richardson 已提交
181
    }
A
Ariel Ben-Yehuda 已提交
182 183

    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
184
        unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
C
Corey Richardson 已提交
185
    }
186

A
Ariel Ben-Yehuda 已提交
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) {
A
Ariel Ben-Yehuda 已提交
192 193 194 195 196
        if set {
            self.apply_llfn(idx, llfn);
        } else {
            self.unapply_llfn(idx, llfn);
        }
197 198 199
    }
}

200
// Memory-managed interface to target data.
201

202 203
struct TargetData {
    lltd: TargetDataRef,
204 205
}

E
Eduard Burtescu 已提交
206
impl Drop for TargetData {
D
Daniel Micay 已提交
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 226 227
impl ObjectFile {
    // This will take ownership of llmb
    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 241 242
impl Drop for ObjectFile {
    fn drop(&mut self) {
        unsafe {
243
            LLVMDisposeObjectFile(self.llof);
244
        }
245
    }
246 247
}

248
// Memory-managed interface to section iterators.
249

E
Eduard Burtescu 已提交
250
pub struct SectionIter {
251
    pub llsi: SectionIteratorRef,
252 253
}

E
Eduard Burtescu 已提交
254
impl Drop for SectionIter {
D
Daniel Micay 已提交
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 267 268
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
    unsafe {
269 270
        assert!(index < LLVMCountParams(llfn),
            "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
271 272 273 274
        LLVMGetParam(llfn, index)
    }
}

275
fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
276 277 278 279 280 281 282 283 284 285 286
    unsafe {
        let num_params = LLVMCountParams(llfn);
        let mut params = Vec::with_capacity(num_params as usize);
        for idx in 0..num_params {
            params.push(LLVMGetParam(llfn, idx));
        }

        params
    }
}

287 288 289
pub fn build_string<F>(f: F) -> Option<String>
    where F: FnOnce(RustStringRef)
{
290 291
    let mut buf = RefCell::new(Vec::new());
    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 unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
300
    build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
301 302 303
        .expect("got a non-UTF8 DebugLoc from LLVM")
}

304 305
pub fn initialize_available_targets() {
    macro_rules! init_target(
306
        ($cfg:meta, $($method:ident),*) => { {
307 308
            #[cfg($cfg)]
            fn init() {
309 310 311
                extern {
                    $(fn $method();)*
                }
312
                unsafe {
313
                    $($method();)*
314 315 316 317 318 319 320
                }
            }
            #[cfg(not($cfg))]
            fn init() { }
            init();
        } }
    );
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
    init_target!(llvm_component = "x86",
                 LLVMInitializeX86TargetInfo,
                 LLVMInitializeX86Target,
                 LLVMInitializeX86TargetMC,
                 LLVMInitializeX86AsmPrinter,
                 LLVMInitializeX86AsmParser);
    init_target!(llvm_component = "arm",
                 LLVMInitializeARMTargetInfo,
                 LLVMInitializeARMTarget,
                 LLVMInitializeARMTargetMC,
                 LLVMInitializeARMAsmPrinter,
                 LLVMInitializeARMAsmParser);
    init_target!(llvm_component = "aarch64",
                 LLVMInitializeAArch64TargetInfo,
                 LLVMInitializeAArch64Target,
                 LLVMInitializeAArch64TargetMC,
                 LLVMInitializeAArch64AsmPrinter,
                 LLVMInitializeAArch64AsmParser);
    init_target!(llvm_component = "mips",
                 LLVMInitializeMipsTargetInfo,
                 LLVMInitializeMipsTarget,
                 LLVMInitializeMipsTargetMC,
                 LLVMInitializeMipsAsmPrinter,
                 LLVMInitializeMipsAsmParser);
    init_target!(llvm_component = "powerpc",
                 LLVMInitializePowerPCTargetInfo,
                 LLVMInitializePowerPCTarget,
                 LLVMInitializePowerPCTargetMC,
                 LLVMInitializePowerPCAsmPrinter,
                 LLVMInitializePowerPCAsmParser);
J
Jorge Aparicio 已提交
351 352 353 354 355 356
    init_target!(llvm_component = "systemz",
                 LLVMInitializeSystemZTargetInfo,
                 LLVMInitializeSystemZTarget,
                 LLVMInitializeSystemZTargetMC,
                 LLVMInitializeSystemZAsmPrinter,
                 LLVMInitializeSystemZAsmParser);
357 358 359 360
    init_target!(llvm_component = "jsbackend",
                 LLVMInitializeJSBackendTargetInfo,
                 LLVMInitializeJSBackendTarget,
                 LLVMInitializeJSBackendTargetMC);
J
Jorge Aparicio 已提交
361 362 363 364 365
    init_target!(llvm_component = "msp430",
                 LLVMInitializeMSP430TargetInfo,
                 LLVMInitializeMSP430Target,
                 LLVMInitializeMSP430TargetMC,
                 LLVMInitializeMSP430AsmPrinter);
J
Jorge Aparicio 已提交
366 367 368 369 370 371
    init_target!(llvm_component = "sparc",
                 LLVMInitializeSparcTargetInfo,
                 LLVMInitializeSparcTarget,
                 LLVMInitializeSparcTargetMC,
                 LLVMInitializeSparcAsmPrinter,
                 LLVMInitializeSparcAsmParser);
J
Jorge Aparicio 已提交
372 373 374 375 376
    init_target!(llvm_component = "nvptx",
                 LLVMInitializeNVPTXTargetInfo,
                 LLVMInitializeNVPTXTarget,
                 LLVMInitializeNVPTXTargetMC,
                 LLVMInitializeNVPTXAsmPrinter);
M
Michael Wu 已提交
377 378 379 380 381 382
    init_target!(llvm_component = "hexagon",
                 LLVMInitializeHexagonTargetInfo,
                 LLVMInitializeHexagonTarget,
                 LLVMInitializeHexagonTargetMC,
                 LLVMInitializeHexagonAsmPrinter,
                 LLVMInitializeHexagonAsmParser);
383 384 385 386 387
    init_target!(llvm_component = "webassembly",
                 LLVMInitializeWebAssemblyTargetInfo,
                 LLVMInitializeWebAssemblyTarget,
                 LLVMInitializeWebAssemblyTargetMC,
                 LLVMInitializeWebAssemblyAsmPrinter);
388 389
}

A
Alex Crichton 已提交
390 391 392 393 394 395 396 397 398 399 400 401 402 403
pub fn last_error() -> Option<String> {
    unsafe {
        let cstr = LLVMRustGetLastError();
        if cstr.is_null() {
            None
        } else {
            let err = CStr::from_ptr(cstr).to_bytes();
            let err = String::from_utf8_lossy(err).to_string();
            libc::free(cstr as *mut _);
            Some(err)
        }
    }
}

404 405 406 407 408 409 410 411
pub struct OperandBundleDef {
    inner: OperandBundleDefRef,
}

impl OperandBundleDef {
    pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
        let name = CString::new(name).unwrap();
        let def = unsafe {
412
            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
        };
        OperandBundleDef { inner: def }
    }

    pub fn raw(&self) -> OperandBundleDefRef {
        self.inner
    }
}

impl Drop for OperandBundleDef {
    fn drop(&mut self) {
        unsafe {
            LLVMRustFreeOperandBundleDef(self.inner);
        }
    }
}