Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement unwinding for i686 MSVC #30448

Merged
merged 3 commits into from
Jan 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(3)))
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(3)))
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
export MSVC_LIB := "$$(CFG_MSVC_LIB_$$(HOST_$(3)))"
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
$(S)src/test/run-make/%/Makefile \
$$(CSREQ$(1)_T_$(2)_H_$(3))
Expand Down
12 changes: 10 additions & 2 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,15 @@ extern "rust-intrinsic" {
pub fn discriminant_value<T>(v: &T) -> u64;

/// Rust's "try catch" construct which invokes the function pointer `f` with
/// the data pointer `data`, returning the exception payload if an exception
/// is thrown (aka the thread panics).
/// the data pointer `data`.
///
/// The third pointer is a target-specific data pointer which is filled in
/// with the specifics of the exception that occurred. For examples on Unix
/// platforms this is a `*mut *mut T` which is filled in by the compiler and
/// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
/// source as well as std's catch implementation.
#[cfg(not(stage0))]
pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
#[cfg(stage0)]
pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
}
1 change: 0 additions & 1 deletion src/librustc_back/target/x86_64_pc_windows_msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use target::Target;
pub fn target() -> Target {
let mut base = super::windows_msvc_base::opts();
base.cpu = "x86-64".to_string();
base.custom_unwind_resume = true;

Target {
llvm_target: "x86_64-pc-windows-msvc".to_string(),
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_llvm/archive_ro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ impl Drop for ArchiveRO {
}

impl<'a> Iterator for Iter<'a> {
type Item = Child<'a>;
type Item = Result<Child<'a>, String>;

fn next(&mut self) -> Option<Child<'a>> {
fn next(&mut self) -> Option<Result<Child<'a>, String>> {
let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
if ptr.is_null() {
None
::last_error().map(Err)
} else {
Some(Child { ptr: ptr, _data: marker::PhantomData })
Some(Ok(Child { ptr: ptr, _data: marker::PhantomData }))
}
}
}
Expand Down
108 changes: 93 additions & 15 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub use self::DiagnosticSeverity::*;
pub use self::Linkage::*;
pub use self::DLLStorageClassTypes::*;

use std::ffi::CString;
use std::ffi::{CString, CStr};
use std::cell::RefCell;
use std::slice;
use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
Expand Down Expand Up @@ -544,6 +544,9 @@ pub type SMDiagnosticRef = *mut SMDiagnostic_opaque;
#[allow(missing_copy_implementations)]
pub enum RustArchiveMember_opaque {}
pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque;
#[allow(missing_copy_implementations)]
pub enum OperandBundleDef_opaque {}
pub type OperandBundleDefRef = *mut OperandBundleDef_opaque;

pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void);
pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint);
Expand Down Expand Up @@ -1149,14 +1152,15 @@ extern {
Addr: ValueRef,
NumDests: c_uint)
-> ValueRef;
pub fn LLVMBuildInvoke(B: BuilderRef,
Fn: ValueRef,
Args: *const ValueRef,
NumArgs: c_uint,
Then: BasicBlockRef,
Catch: BasicBlockRef,
Name: *const c_char)
-> ValueRef;
pub fn LLVMRustBuildInvoke(B: BuilderRef,
Fn: ValueRef,
Args: *const ValueRef,
NumArgs: c_uint,
Then: BasicBlockRef,
Catch: BasicBlockRef,
Bundle: OperandBundleDefRef,
Name: *const c_char)
-> ValueRef;
pub fn LLVMRustBuildLandingPad(B: BuilderRef,
Ty: TypeRef,
PersFn: ValueRef,
Expand All @@ -1167,6 +1171,31 @@ extern {
pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef;
pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef;

pub fn LLVMRustBuildCleanupPad(B: BuilderRef,
ParentPad: ValueRef,
ArgCnt: c_uint,
Args: *const ValueRef,
Name: *const c_char) -> ValueRef;
pub fn LLVMRustBuildCleanupRet(B: BuilderRef,
CleanupPad: ValueRef,
UnwindBB: BasicBlockRef) -> ValueRef;
pub fn LLVMRustBuildCatchPad(B: BuilderRef,
ParentPad: ValueRef,
ArgCnt: c_uint,
Args: *const ValueRef,
Name: *const c_char) -> ValueRef;
pub fn LLVMRustBuildCatchRet(B: BuilderRef,
Pad: ValueRef,
BB: BasicBlockRef) -> ValueRef;
pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef,
ParentPad: ValueRef,
BB: BasicBlockRef,
NumHandlers: c_uint,
Name: *const c_char) -> ValueRef;
pub fn LLVMRustAddHandler(CatchSwitch: ValueRef,
Handler: BasicBlockRef);
pub fn LLVMRustSetPersonalityFn(B: BuilderRef, Pers: ValueRef);

/* Add a case to the switch instruction */
pub fn LLVMAddCase(Switch: ValueRef,
OnVal: ValueRef,
Expand Down Expand Up @@ -1476,12 +1505,13 @@ extern {
/* Miscellaneous instructions */
pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char)
-> ValueRef;
pub fn LLVMBuildCall(B: BuilderRef,
Fn: ValueRef,
Args: *const ValueRef,
NumArgs: c_uint,
Name: *const c_char)
-> ValueRef;
pub fn LLVMRustBuildCall(B: BuilderRef,
Fn: ValueRef,
Args: *const ValueRef,
NumArgs: c_uint,
Bundle: OperandBundleDefRef,
Name: *const c_char)
-> ValueRef;
pub fn LLVMBuildSelect(B: BuilderRef,
If: ValueRef,
Then: ValueRef,
Expand Down Expand Up @@ -2126,6 +2156,12 @@ extern {
pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef,
TM: TargetMachineRef);
pub fn LLVMRustGetModuleDataLayout(M: ModuleRef) -> TargetDataRef;

pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char,
Inputs: *const ValueRef,
NumInputs: c_uint)
-> OperandBundleDefRef;
pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef);
}

#[cfg(have_component_x86)]
Expand Down Expand Up @@ -2404,6 +2440,48 @@ pub fn initialize_available_targets() {
init_pnacl();
}

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)
}
}
}

pub struct OperandBundleDef {
inner: OperandBundleDefRef,
}

impl OperandBundleDef {
pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef {
let name = CString::new(name).unwrap();
let def = unsafe {
LLVMRustBuildOperandBundleDef(name.as_ptr(),
vals.as_ptr(),
vals.len() as c_uint)
};
OperandBundleDef { inner: def }
}

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

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

// 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.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ pub fn note_crate_name(err: &mut DiagnosticBuilder, name: &str) {
impl ArchiveMetadata {
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
let data = {
let section = ar.iter().find(|sect| {
let section = ar.iter().filter_map(|s| s.ok()).find(|sect| {
sect.name() == Some(METADATA_FILENAME)
});
match section {
Expand Down
37 changes: 32 additions & 5 deletions src/librustc_trans/back/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl<'a> ArchiveBuilder<'a> {
}
let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
let ret = archive.iter()
.filter_map(|child| child.ok())
.filter(is_relevant_child)
.filter_map(|child| child.name())
.filter(|name| !self.removals.iter().any(|x| x == name))
Expand Down Expand Up @@ -332,9 +333,15 @@ impl<'a> ArchiveBuilder<'a> {
// We skip any files explicitly desired for skipping, and we also skip
// all SYMDEF files as these are just magical placeholders which get
// re-created when we make a new archive anyway.
for file in archive.iter().filter(is_relevant_child) {
for file in archive.iter() {
let file = try!(file.map_err(string_to_io_error));
if !is_relevant_child(&file) {
continue
}
let filename = file.name().unwrap();
if skip(filename) { continue }
if skip(filename) {
continue
}
let filename = Path::new(filename).file_name().unwrap()
.to_str().unwrap();

Expand Down Expand Up @@ -448,6 +455,7 @@ impl<'a> ArchiveBuilder<'a> {
unsafe {
if let Some(archive) = self.src_archive() {
for child in archive.iter() {
let child = try!(child.map_err(string_to_io_error));
let child_name = match child.name() {
Some(s) => s,
None => continue,
Expand Down Expand Up @@ -475,10 +483,25 @@ impl<'a> ArchiveBuilder<'a> {
strings.push(name);
}
Addition::Archive { archive, archive_name: _, mut skip } => {
for child in archive.iter().filter(is_relevant_child) {
for child in archive.iter() {
let child = try!(child.map_err(string_to_io_error));
if !is_relevant_child(&child) {
continue
}
let child_name = child.name().unwrap();
if skip(child_name) { continue }

if skip(child_name) {
continue
}

// It appears that LLVM's archive writer is a little
// buggy if the name we pass down isn't just the
// filename component, so chop that off here and
// pass it in.
//
// See LLVM bug 25877 for more info.
let child_name = Path::new(child_name)
.file_name().unwrap()
.to_str().unwrap();
let name = try!(CString::new(child_name));
let m = llvm::LLVMRustArchiveMemberNew(ptr::null(),
name.as_ptr(),
Expand Down Expand Up @@ -517,3 +540,7 @@ impl<'a> ArchiveBuilder<'a> {
}
}
}

fn string_to_io_error(s: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("bad archive: {}", s))
}
2 changes: 1 addition & 1 deletion src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
link::each_linked_rlib(sess, &mut |_, path| {
let archive = ArchiveRO::open(&path).expect("wanted an rlib");
let bytecodes = archive.iter().filter_map(|child| {
child.name().map(|name| (name, child))
child.ok().and_then(|c| c.name().map(|name| (name, c)))
}).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
for (name, data) in bytecodes {
let bc_encoded = data.data();
Expand Down
16 changes: 4 additions & 12 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,16 @@ use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::fs;
use std::path::{Path, PathBuf};
use std::ptr;
use std::str;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;
use std::thread;
use libc::{self, c_uint, c_int, c_void};
use libc::{c_uint, c_int, c_void};

pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
unsafe {
let cstr = llvm::LLVMRustGetLastError();
if cstr == ptr::null() {
panic!(handler.fatal(&msg[..]));
} else {
let err = CStr::from_ptr(cstr).to_bytes();
let err = String::from_utf8_lossy(err).to_string();
libc::free(cstr as *mut _);
panic!(handler.fatal(&format!("{}: {}", &msg[..], &err[..])));
}
match llvm::last_error() {
Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
None => panic!(handler.fatal(&msg)),
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1271,7 +1271,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
};
}
Variant(_, ref repr, _, _) => {
let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val.val);
let (the_kind, val_opt) = adt::trans_switch(bcx, &repr,
val.val, true);
kind = the_kind;
if let Some(tval) = val_opt { test_val = tval; }
}
Expand Down
Loading