rust/src/librustc_llvm/lib.rs

428 lines
13 KiB
Rust
Raw Normal View History

// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// 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.
2014-10-27 15:37:07 -07:00
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
2014-04-01 10:17:18 -04:00
#![allow(dead_code)]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![deny(warnings)]
2014-07-05 13:24:57 -07:00
#![feature(box_syntax)]
#![feature(concat_idents)]
#![feature(libc)]
#![feature(link_args)]
#![feature(static_nobundle)]
2014-07-05 13:24:57 -07:00
extern crate libc;
#[macro_use]
#[no_link]
extern crate rustc_bitflags;
pub use self::IntPredicate::*;
pub use self::RealPredicate::*;
pub use self::TypeKind::*;
pub use self::AtomicRmwBinOp::*;
pub use self::MetadataType::*;
pub use self::CodeGenOptSize::*;
pub use self::CallConv::*;
pub use self::Linkage::*;
use std::str::FromStr;
use std::slice;
use std::ffi::{CString, CStr};
2014-09-09 23:12:09 -07:00
use std::cell::RefCell;
2016-08-03 00:25:19 +03:00
use libc::{c_uint, c_char, size_t};
2013-06-15 22:16:47 +12:00
pub mod archive_ro;
pub mod diagnostic;
2017-08-19 03:09:55 +03:00
mod ffi;
pub use ffi::*;
impl LLVMRustResult {
pub fn into_result(self) -> Result<(), ()> {
match self {
LLVMRustResult::Success => Ok(()),
LLVMRustResult::Failure => Err(()),
}
}
}
2016-10-22 18:37:35 +05:30
pub fn AddFunctionAttrStringValue(llfn: ValueRef,
idx: AttributePlace,
attr: &CStr,
value: &CStr) {
2016-08-03 00:25:19 +03:00
unsafe {
2016-10-22 18:37:35 +05:30
LLVMRustAddFunctionAttrStringValue(llfn,
idx.as_uint(),
attr.as_ptr(),
value.as_ptr())
2016-08-03 00:25:19 +03:00
}
}
#[repr(C)]
#[derive(Copy, Clone)]
2016-08-03 00:25:19 +03:00
pub enum AttributePlace {
Argument(u32),
Function,
}
impl AttributePlace {
pub fn ReturnValue() -> Self {
AttributePlace::Argument(0)
}
pub fn as_uint(self) -> c_uint {
2016-08-03 00:25:19 +03:00
match self {
AttributePlace::Function => !0,
AttributePlace::Argument(i) => i,
}
}
}
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CodeGenOptSize {
CodeGenOptSizeNone = 0,
CodeGenOptSizeDefault = 1,
CodeGenOptSizeAggressive = 2,
}
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(()),
}
}
}
#[allow(missing_copy_implementations)]
pub enum RustString_opaque {}
2017-08-19 03:09:55 +03:00
type RustStringRef = *mut RustString_opaque;
type RustStringRepr = *mut RefCell<Vec<u8>>;
/// Appending to a Rust string -- used by RawRustStringOstream.
#[no_mangle]
pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
ptr: *const c_char,
size: size_t) {
let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
let sr = sr as RustStringRepr;
(*sr).borrow_mut().extend_from_slice(slice);
}
pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) {
unsafe {
LLVMSetInstructionCallConv(instr, cc as c_uint);
}
}
pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) {
unsafe {
LLVMSetFunctionCallConv(fn_, cc as c_uint);
}
}
// 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);
}
}
pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) {
unsafe {
LLVMSetUnnamedAddr(global, unnamed as Bool);
}
}
pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
unsafe {
LLVMSetThreadLocal(global, is_thread_local as Bool);
}
}
2016-08-03 00:25:19 +03:00
impl Attribute {
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
2013-05-19 20:18:56 -04:00
}
2016-08-03 00:25:19 +03:00
pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
2013-05-19 20:18:56 -04:00
}
2016-08-03 00:25:19 +03:00
pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
}
2014-07-05 13:24:57 -07:00
2016-10-22 18:37:35 +05:30
pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
2016-08-03 00:25:19 +03:00
if set {
self.apply_llfn(idx, llfn);
} else {
self.unapply_llfn(idx, llfn);
}
}
}
2016-10-22 18:37:35 +05:30
// Memory-managed interface to target data.
2017-08-19 03:09:55 +03:00
struct TargetData {
lltd: TargetDataRef,
}
2014-04-22 03:53:51 +03:00
impl Drop for TargetData {
2013-09-16 21:18:07 -04:00
fn drop(&mut self) {
unsafe {
LLVMDisposeTargetData(self.lltd);
}
}
}
2017-08-19 03:09:55 +03:00
fn mk_target_data(string_rep: &str) -> TargetData {
std: Implement CString-related RFCs This commit is an implementation of [RFC 592][r592] and [RFC 840][r840]. These two RFCs tweak the behavior of `CString` and add a new `CStr` unsized slice type to the module. [r592]: https://github.com/rust-lang/rfcs/blob/master/text/0592-c-str-deref.md [r840]: https://github.com/rust-lang/rfcs/blob/master/text/0840-no-panic-in-c-string.md The new `CStr` type is only constructable via two methods: 1. By `deref`'ing from a `CString` 2. Unsafely via `CStr::from_ptr` The purpose of `CStr` is to be an unsized type which is a thin pointer to a `libc::c_char` (currently it is a fat pointer slice due to implementation limitations). Strings from C can be safely represented with a `CStr` and an appropriate lifetime as well. Consumers of `&CString` should now consume `&CStr` instead to allow producers to pass in C-originating strings instead of just Rust-allocated strings. A new constructor was added to `CString`, `new`, which takes `T: IntoBytes` instead of separate `from_slice` and `from_vec` methods (both have been deprecated in favor of `new`). The `new` method returns a `Result` instead of panicking. The error variant contains the relevant information about where the error happened and bytes (if present). Conversions are provided to the `io::Error` and `old_io::IoError` types via the `FromError` trait which translate to `InvalidInput`. This is a breaking change due to the modification of existing `#[unstable]` APIs and new deprecation, and more detailed information can be found in the two RFCs. Notable breakage includes: * All construction of `CString` now needs to use `new` and handle the outgoing `Result`. * Usage of `CString` as a byte slice now explicitly needs a `.as_bytes()` call. * The `as_slice*` methods have been removed in favor of just having the `as_bytes*` methods. Closes #22469 Closes #22470 [breaking-change]
2015-02-17 22:47:40 -08:00
let string_rep = CString::new(string_rep).unwrap();
2016-10-22 18:37:35 +05:30
TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } }
}
2016-10-22 18:37:35 +05:30
// Memory-managed interface to object files.
Add generation of static libraries to rustc This commit implements the support necessary for generating both intermediate and result static rust libraries. This is an implementation of my thoughts in https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html. When compiling a library, we still retain the "lib" option, although now there are "rlib", "staticlib", and "dylib" as options for crate_type (and these are stackable). The idea of "lib" is to generate the "compiler default" instead of having too choose (although all are interchangeable). For now I have left the "complier default" to be a dynamic library for size reasons. Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a dynamic object. I chose this for size reasons, but also because you're probably not going to be embedding the rustc compiler anywhere any time soon. Other than the options outlined above, there are a few defaults/preferences that are now opinionated in the compiler: * If both a .dylib and .rlib are found for a rust library, the compiler will prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option * If generating a "lib", the compiler will generate a dynamic library. This is overridable by explicitly saying what flavor you'd like (rlib, staticlib, dylib). * If no options are passed to the command line, and no crate_type is found in the destination crate, then an executable is generated With this change, you can successfully build a rust program with 0 dynamic dependencies on rust libraries. There is still a dynamic dependency on librustrt, but I plan on removing that in a subsequent commit. This change includes no tests just yet. Our current testing infrastructure/harnesses aren't very amenable to doing flavorful things with linking, so I'm planning on adding a new mode of testing which I believe belongs as a separate commit. Closes #552
2013-11-15 14:03:29 -08:00
pub struct ObjectFile {
pub llof: ObjectFileRef,
}
Add generation of static libraries to rustc This commit implements the support necessary for generating both intermediate and result static rust libraries. This is an implementation of my thoughts in https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html. When compiling a library, we still retain the "lib" option, although now there are "rlib", "staticlib", and "dylib" as options for crate_type (and these are stackable). The idea of "lib" is to generate the "compiler default" instead of having too choose (although all are interchangeable). For now I have left the "complier default" to be a dynamic library for size reasons. Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a dynamic object. I chose this for size reasons, but also because you're probably not going to be embedding the rustc compiler anywhere any time soon. Other than the options outlined above, there are a few defaults/preferences that are now opinionated in the compiler: * If both a .dylib and .rlib are found for a rust library, the compiler will prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option * If generating a "lib", the compiler will generate a dynamic library. This is overridable by explicitly saying what flavor you'd like (rlib, staticlib, dylib). * If no options are passed to the command line, and no crate_type is found in the destination crate, then an executable is generated With this change, you can successfully build a rust program with 0 dynamic dependencies on rust libraries. There is still a dynamic dependency on librustrt, but I plan on removing that in a subsequent commit. This change includes no tests just yet. Our current testing infrastructure/harnesses aren't very amenable to doing flavorful things with linking, so I'm planning on adding a new mode of testing which I believe belongs as a separate commit. Closes #552
2013-11-15 14:03:29 -08:00
impl ObjectFile {
// This will take ownership of llmb
pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
unsafe {
let llof = LLVMCreateObjectFile(llmb);
if llof as isize == 0 {
// LLVMCreateObjectFile took ownership of llmb
2016-10-22 18:37:35 +05:30
return None;
Add generation of static libraries to rustc This commit implements the support necessary for generating both intermediate and result static rust libraries. This is an implementation of my thoughts in https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html. When compiling a library, we still retain the "lib" option, although now there are "rlib", "staticlib", and "dylib" as options for crate_type (and these are stackable). The idea of "lib" is to generate the "compiler default" instead of having too choose (although all are interchangeable). For now I have left the "complier default" to be a dynamic library for size reasons. Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a dynamic object. I chose this for size reasons, but also because you're probably not going to be embedding the rustc compiler anywhere any time soon. Other than the options outlined above, there are a few defaults/preferences that are now opinionated in the compiler: * If both a .dylib and .rlib are found for a rust library, the compiler will prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option * If generating a "lib", the compiler will generate a dynamic library. This is overridable by explicitly saying what flavor you'd like (rlib, staticlib, dylib). * If no options are passed to the command line, and no crate_type is found in the destination crate, then an executable is generated With this change, you can successfully build a rust program with 0 dynamic dependencies on rust libraries. There is still a dynamic dependency on librustrt, but I plan on removing that in a subsequent commit. This change includes no tests just yet. Our current testing infrastructure/harnesses aren't very amenable to doing flavorful things with linking, so I'm planning on adding a new mode of testing which I believe belongs as a separate commit. Closes #552
2013-11-15 14:03:29 -08:00
}
2016-10-22 18:37:35 +05:30
Some(ObjectFile { llof: llof })
}
}
}
Add generation of static libraries to rustc This commit implements the support necessary for generating both intermediate and result static rust libraries. This is an implementation of my thoughts in https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html. When compiling a library, we still retain the "lib" option, although now there are "rlib", "staticlib", and "dylib" as options for crate_type (and these are stackable). The idea of "lib" is to generate the "compiler default" instead of having too choose (although all are interchangeable). For now I have left the "complier default" to be a dynamic library for size reasons. Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a dynamic object. I chose this for size reasons, but also because you're probably not going to be embedding the rustc compiler anywhere any time soon. Other than the options outlined above, there are a few defaults/preferences that are now opinionated in the compiler: * If both a .dylib and .rlib are found for a rust library, the compiler will prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option * If generating a "lib", the compiler will generate a dynamic library. This is overridable by explicitly saying what flavor you'd like (rlib, staticlib, dylib). * If no options are passed to the command line, and no crate_type is found in the destination crate, then an executable is generated With this change, you can successfully build a rust program with 0 dynamic dependencies on rust libraries. There is still a dynamic dependency on librustrt, but I plan on removing that in a subsequent commit. This change includes no tests just yet. Our current testing infrastructure/harnesses aren't very amenable to doing flavorful things with linking, so I'm planning on adding a new mode of testing which I believe belongs as a separate commit. Closes #552
2013-11-15 14:03:29 -08:00
impl Drop for ObjectFile {
fn drop(&mut self) {
unsafe {
LLVMDisposeObjectFile(self.llof);
Add generation of static libraries to rustc This commit implements the support necessary for generating both intermediate and result static rust libraries. This is an implementation of my thoughts in https://mail.mozilla.org/pipermail/rust-dev/2013-November/006686.html. When compiling a library, we still retain the "lib" option, although now there are "rlib", "staticlib", and "dylib" as options for crate_type (and these are stackable). The idea of "lib" is to generate the "compiler default" instead of having too choose (although all are interchangeable). For now I have left the "complier default" to be a dynamic library for size reasons. Of the rust libraries, lib{std,extra,rustuv} will bootstrap with an rlib/dylib pair, but lib{rustc,syntax,rustdoc,rustpkg} will only be built as a dynamic object. I chose this for size reasons, but also because you're probably not going to be embedding the rustc compiler anywhere any time soon. Other than the options outlined above, there are a few defaults/preferences that are now opinionated in the compiler: * If both a .dylib and .rlib are found for a rust library, the compiler will prefer the .rlib variant. This is overridable via the -Z prefer-dynamic option * If generating a "lib", the compiler will generate a dynamic library. This is overridable by explicitly saying what flavor you'd like (rlib, staticlib, dylib). * If no options are passed to the command line, and no crate_type is found in the destination crate, then an executable is generated With this change, you can successfully build a rust program with 0 dynamic dependencies on rust libraries. There is still a dynamic dependency on librustrt, but I plan on removing that in a subsequent commit. This change includes no tests just yet. Our current testing infrastructure/harnesses aren't very amenable to doing flavorful things with linking, so I'm planning on adding a new mode of testing which I believe belongs as a separate commit. Closes #552
2013-11-15 14:03:29 -08:00
}
}
}
2016-10-22 18:37:35 +05:30
// Memory-managed interface to section iterators.
2014-04-22 03:53:51 +03:00
pub struct SectionIter {
2016-10-22 18:37:35 +05:30
pub llsi: SectionIteratorRef,
}
2014-04-22 03:53:51 +03:00
impl Drop for SectionIter {
2013-09-16 21:18:07 -04:00
fn drop(&mut self) {
unsafe {
LLVMDisposeSectionIterator(self.llsi);
}
}
}
pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
2016-10-22 18:37:35 +05:30
unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
}
2014-07-05 13:24:57 -07:00
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
unsafe {
assert!(index < LLVMCountParams(llfn),
"out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn));
LLVMGetParam(llfn, index)
}
}
2017-08-19 03:09:55 +03:00
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
}
}
2016-10-22 18:37:35 +05:30
pub fn build_string<F>(f: F) -> Option<String>
where F: FnOnce(RustStringRef)
{
2014-09-09 23:12:09 -07:00
let mut buf = RefCell::new(Vec::new());
f(&mut buf as RustStringRepr as RustStringRef);
String::from_utf8(buf.into_inner()).ok()
2014-09-09 23:12:09 -07:00
}
pub unsafe fn twine_to_string(tr: TwineRef) -> String {
2016-10-22 18:37:35 +05:30
build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM")
}
pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String {
build_string(|s| LLVMRustWriteDebugLocToString(c, tr, s))
.expect("got a non-UTF8 DebugLoc from LLVM")
}
pub fn initialize_available_targets() {
macro_rules! init_target(
($cfg:meta, $($method:ident),*) => { {
#[cfg($cfg)]
fn init() {
extern {
$(fn $method();)*
}
unsafe {
$($method();)*
}
}
#[cfg(not($cfg))]
fn init() { }
init();
} }
);
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);
init_target!(llvm_component = "systemz",
LLVMInitializeSystemZTargetInfo,
LLVMInitializeSystemZTarget,
LLVMInitializeSystemZTargetMC,
LLVMInitializeSystemZAsmPrinter,
LLVMInitializeSystemZAsmParser);
init_target!(llvm_component = "jsbackend",
LLVMInitializeJSBackendTargetInfo,
LLVMInitializeJSBackendTarget,
LLVMInitializeJSBackendTargetMC);
init_target!(llvm_component = "msp430",
LLVMInitializeMSP430TargetInfo,
LLVMInitializeMSP430Target,
LLVMInitializeMSP430TargetMC,
LLVMInitializeMSP430AsmPrinter);
2016-12-11 23:12:46 -05:00
init_target!(llvm_component = "sparc",
LLVMInitializeSparcTargetInfo,
LLVMInitializeSparcTarget,
LLVMInitializeSparcTargetMC,
LLVMInitializeSparcAsmPrinter,
LLVMInitializeSparcAsmParser);
init_target!(llvm_component = "nvptx",
LLVMInitializeNVPTXTargetInfo,
LLVMInitializeNVPTXTarget,
LLVMInitializeNVPTXTargetMC,
LLVMInitializeNVPTXAsmPrinter);
init_target!(llvm_component = "hexagon",
LLVMInitializeHexagonTargetInfo,
LLVMInitializeHexagonTarget,
LLVMInitializeHexagonTargetMC,
LLVMInitializeHexagonAsmPrinter,
LLVMInitializeHexagonAsmParser);
init_target!(llvm_component = "webassembly",
LLVMInitializeWebAssemblyTargetInfo,
LLVMInitializeWebAssemblyTarget,
LLVMInitializeWebAssemblyTargetMC,
LLVMInitializeWebAssemblyAsmPrinter);
}
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)
}
}
}
trans: Reimplement unwinding on MSVC This commit transitions the compiler to using the new exception handling instructions in LLVM for implementing unwinding for MSVC. This affects both 32 and 64-bit MSVC as they're both now using SEH-based strategies. In terms of standard library support, lots more details about how SEH unwinding is implemented can be found in the commits. In terms of trans, this change necessitated a few modifications: * Branches were added to detect when the old landingpad instruction is used or the new cleanuppad instruction is used to `trans::cleanup`. * The return value from `cleanuppad` is not stored in an `alloca` (because it cannot be). * Each block in trans now has an `Option<LandingPad>` instead of `is_lpad: bool` for indicating whether it's in a landing pad or not. The new exception handling intrinsics require that on MSVC each `call` inside of a landing pad is annotated with which landing pad that it's in. This change to the basic block means that whenever a `call` or `invoke` instruction is generated we know whether to annotate it as part of a cleanuppad or not. * Lots of modifications were made to the instruction builders to construct the new instructions as well as pass the tagging information for the call/invoke instructions. * The translation of the `try` intrinsics for MSVC has been overhauled to use the new `catchpad` instruction. The filter function is now also a rustc-generated function instead of a purely libstd-defined function. The libstd definition still exists, it just has a stable ABI across architectures and leaves some of the really weird implementation details to the compiler (e.g. the `localescape` and `localrecover` intrinsics).
2015-10-23 18:18:44 -07:00
pub struct OperandBundleDef {
inner: OperandBundleDefRef,
}
impl OperandBundleDef {
pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
let name = CString::new(name).unwrap();
let def = unsafe {
2016-10-22 18:37:35 +05:30
LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint)
trans: Reimplement unwinding on MSVC This commit transitions the compiler to using the new exception handling instructions in LLVM for implementing unwinding for MSVC. This affects both 32 and 64-bit MSVC as they're both now using SEH-based strategies. In terms of standard library support, lots more details about how SEH unwinding is implemented can be found in the commits. In terms of trans, this change necessitated a few modifications: * Branches were added to detect when the old landingpad instruction is used or the new cleanuppad instruction is used to `trans::cleanup`. * The return value from `cleanuppad` is not stored in an `alloca` (because it cannot be). * Each block in trans now has an `Option<LandingPad>` instead of `is_lpad: bool` for indicating whether it's in a landing pad or not. The new exception handling intrinsics require that on MSVC each `call` inside of a landing pad is annotated with which landing pad that it's in. This change to the basic block means that whenever a `call` or `invoke` instruction is generated we know whether to annotate it as part of a cleanuppad or not. * Lots of modifications were made to the instruction builders to construct the new instructions as well as pass the tagging information for the call/invoke instructions. * The translation of the `try` intrinsics for MSVC has been overhauled to use the new `catchpad` instruction. The filter function is now also a rustc-generated function instead of a purely libstd-defined function. The libstd definition still exists, it just has a stable ABI across architectures and leaves some of the really weird implementation details to the compiler (e.g. the `localescape` and `localrecover` intrinsics).
2015-10-23 18:18:44 -07:00
};
OperandBundleDef { inner: def }
}
pub fn raw(&self) -> OperandBundleDefRef {
self.inner
}
}
impl Drop for OperandBundleDef {
fn drop(&mut self) {
unsafe {
LLVMRustFreeOperandBundleDef(self.inner);
}
}
}