lib.rs 12.2 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
#![crate_name = "rustc_llvm"]
17
#![unstable(feature = "rustc_private", issue = "27812")]
18 19
#![crate_type = "dylib"]
#![crate_type = "rlib"]
20
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
A
Alex Crichton 已提交
21
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
22
       html_root_url = "https://doc.rust-lang.org/nightly/")]
23
#![cfg_attr(not(stage0), deny(warnings))]
24

T
Fallout  
Tamir Duberstein 已提交
25
#![feature(associated_consts)]
26
#![feature(box_syntax)]
27
#![feature(libc)]
A
Alex Crichton 已提交
28 29
#![feature(link_args)]
#![feature(staged_api)]
A
Alex Crichton 已提交
30
#![feature(linked_from)]
31
#![feature(concat_idents)]
32 33

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 42 43
pub use self::DiagnosticKind::*;
pub use self::CallConv::*;
pub use self::DiagnosticSeverity::*;
S
Steven Fackler 已提交
44
pub use self::Linkage::*;
S
Steven Fackler 已提交
45

J
Jake Goulding 已提交
46
use std::str::FromStr;
47
use std::slice;
A
Alex Crichton 已提交
48
use std::ffi::{CString, CStr};
49
use std::cell::RefCell;
A
Ariel Ben-Yehuda 已提交
50
use libc::{c_uint, c_char, size_t};
51

52
pub mod archive_ro;
53
pub mod diagnostic;
54
pub mod ffi;
55

56
pub use ffi::*;
57 58 59 60 61 62 63 64 65 66

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

67 68 69 70
pub fn AddFunctionAttrStringValue(llfn: ValueRef,
                                  idx: AttributePlace,
                                  attr: &'static str,
                                  value: &'static str) {
A
Ariel Ben-Yehuda 已提交
71
    unsafe {
72 73 74 75
        LLVMRustAddFunctionAttrStringValue(llfn,
                                           idx.as_uint(),
                                           attr.as_ptr() as *const _,
                                           value.as_ptr() as *const _)
A
Ariel Ben-Yehuda 已提交
76 77 78
    }
}

79 80
#[repr(C)]
#[derive(Copy, Clone)]
A
Ariel Ben-Yehuda 已提交
81 82 83 84 85 86 87 88 89 90
pub enum AttributePlace {
    Argument(u32),
    Function,
}

impl AttributePlace {
    pub fn ReturnValue() -> Self {
        AttributePlace::Argument(0)
    }

91
    pub fn as_uint(self) -> c_uint {
A
Ariel Ben-Yehuda 已提交
92 93 94 95 96
        match self {
            AttributePlace::Function => !0,
            AttributePlace::Argument(i) => i,
        }
    }
97 98
}

99 100 101 102 103 104 105 106
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CodeGenOptSize {
    CodeGenOptSizeNone = 0,
    CodeGenOptSizeDefault = 1,
    CodeGenOptSizeAggressive = 2,
}

J
Jake Goulding 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120
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(()),
        }
    }
}

121
#[allow(missing_copy_implementations)]
122 123 124
pub enum RustString_opaque {}
pub type RustStringRef = *mut RustString_opaque;
type RustStringRepr = *mut RefCell<Vec<u8>>;
125

126 127 128 129 130 131
/// Appending to a Rust string -- used by raw_rust_string_ostream.
#[no_mangle]
pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
                                                     ptr: *const c_char,
                                                     size: size_t) {
    let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
132

133 134
    let sr = sr as RustStringRepr;
    (*sr).borrow_mut().extend_from_slice(slice);
135
}
136

137
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
138
    unsafe {
139
        LLVMSetInstructionCallConv(instr, cc as c_uint);
140
    }
141
}
142
pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
143
    unsafe {
144
        LLVMSetFunctionCallConv(fn_, cc as c_uint);
145
    }
146 147
}

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
// 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);
    }
}

166
pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
167
    unsafe {
168
        LLVMSetUnnamedAddr(global, unnamed as Bool);
169 170 171
    }
}

D
Daniel Micay 已提交
172 173
pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
    unsafe {
174
        LLVMSetThreadLocal(global, is_thread_local as Bool);
D
Daniel Micay 已提交
175 176 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

E
Eduard Burtescu 已提交
202
pub struct TargetData {
203
    pub 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
pub 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 269 270 271 272 273
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
    unsafe {
        assert!(index < LLVMCountParams(llfn));
        LLVMGetParam(llfn, index)
    }
}

274 275 276 277 278 279 280 281 282 283 284 285
pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
    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
    }
}

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

303 304
pub fn initialize_available_targets() {
    macro_rules! init_target(
305
        ($cfg:meta, $($method:ident),*) => { {
306 307
            #[cfg($cfg)]
            fn init() {
308 309 310
                extern {
                    $(fn $method();)*
                }
311
                unsafe {
312
                    $($method();)*
313 314 315 316 317 318 319
                }
            }
            #[cfg(not($cfg))]
            fn init() { }
            init();
        } }
    );
320 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 351 352 353
    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);
    init_target!(llvm_component = "pnacl",
                 LLVMInitializePNaClTargetInfo,
                 LLVMInitializePNaClTarget,
                 LLVMInitializePNaClTargetMC);
J
Jorge Aparicio 已提交
354 355 356 357 358 359
    init_target!(llvm_component = "systemz",
                 LLVMInitializeSystemZTargetInfo,
                 LLVMInitializeSystemZTarget,
                 LLVMInitializeSystemZTargetMC,
                 LLVMInitializeSystemZAsmPrinter,
                 LLVMInitializeSystemZAsmParser);
360 361 362 363
    init_target!(llvm_component = "jsbackend",
                 LLVMInitializeJSBackendTargetInfo,
                 LLVMInitializeJSBackendTarget,
                 LLVMInitializeJSBackendTargetMC);
J
Jorge Aparicio 已提交
364 365 366 367 368
    init_target!(llvm_component = "msp430",
                 LLVMInitializeMSP430TargetInfo,
                 LLVMInitializeMSP430Target,
                 LLVMInitializeMSP430TargetMC,
                 LLVMInitializeMSP430AsmPrinter);
369 370
}

A
Alex Crichton 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384
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)
        }
    }
}

385 386 387 388 389 390 391 392
pub struct OperandBundleDef {
    inner: OperandBundleDefRef,
}

impl OperandBundleDef {
    pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
        let name = CString::new(name).unwrap();
        let def = unsafe {
393
            LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
        };
        OperandBundleDef { inner: def }
    }

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

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

411 412 413 414 415
// The module containing the native LLVM dependencies, generated by the build system
// Note that this must come after the rustllvm extern declaration so that
// parts of LLVM that rustllvm depends on aren't thrown away by the linker.
// Works to the above fix for #15460 to ensure LLVM dependencies that
// are only used by rustllvm don't get stripped by the linker.
416
#[cfg(not(cargobuild))]
417
mod llvmdeps {
418
    include! { env!("CFG_LLVM_LINKAGE_FILE") }
419
}