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

trans: Move rust_try into the compiler #27176

Merged
merged 1 commit into from
Jul 22, 2015
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
18 changes: 0 additions & 18 deletions mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,6 @@ NATIVE_DEPS_miniz_$(1) = miniz.c
NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
rust_android_dummy.c
NATIVE_DEPS_rustrt_native_$(1) := arch/$$(HOST_$(1))/record_sp.S
ifeq ($$(findstring msvc,$(1)),msvc)
ifeq ($$(findstring i686,$(1)),i686)
NATIVE_DEPS_rustrt_native_$(1) += rust_try_msvc_32.ll
else
NATIVE_DEPS_rustrt_native_$(1) += rust_try_msvc_64.ll
endif
else
NATIVE_DEPS_rustrt_native_$(1) += rust_try.ll
endif
NATIVE_DEPS_rust_test_helpers_$(1) := rust_test_helpers.c
NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S

Expand All @@ -76,14 +67,6 @@ NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S

RT_OUTPUT_DIR_$(1) := $(1)/rt

$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.ll $$(MKFILE_DEPS) \
$$(LLVM_CONFIG_$$(CFG_BUILD))
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(LLC_$$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) \
-filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) \
-relocation-model=pic -o $$@ $$<

$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
Expand Down Expand Up @@ -122,7 +105,6 @@ define THIRD_PARTY_LIB
OBJS_$(2)_$(1) := $$(NATIVE_DEPS_$(2)_$(1):%=$$(RT_OUTPUT_DIR_$(1))/%)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.c=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.cpp=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.ll=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.S=.o)
NATIVE_$(2)_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$(2))
$$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,10 @@ extern "rust-intrinsic" {
/// Returns the value of the discriminant for the variant in 'v',
/// cast to a `u64`; if `T` has no discriminant, returns 0.
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).
#[cfg(not(stage0))]
pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
}
2 changes: 2 additions & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ lets_do_this! {
StartFnLangItem, "start", start_fn;

EhPersonalityLangItem, "eh_personality", eh_personality;
EhPersonalityCatchLangItem, "eh_personality_catch", eh_personality_catch;
MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter;

ExchangeHeapLangItem, "exchange_heap", exchange_heap;
OwnedBoxLangItem, "owned_box", owned_box;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/weak_lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
) }

weak_lang_items! {
panic_fmt, PanicFmtLangItem, rust_begin_unwind;
panic_fmt, PanicFmtLangItem, rust_begin_unwind;
stack_exhausted, StackExhaustedLangItem, rust_stack_exhausted;
eh_personality, EhPersonalityLangItem, rust_eh_personality;
}
6 changes: 4 additions & 2 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ pub enum DLLStorageClassTypes {
}

bitflags! {
flags Attribute : u32 {
flags Attribute : u64 {
const ZExt = 1 << 0,
const SExt = 1 << 1,
const NoReturn = 1 << 2,
Expand All @@ -161,6 +161,7 @@ bitflags! {
const ReturnsTwice = 1 << 29,
const UWTable = 1 << 30,
const NonLazyBind = 1 << 31,
const OptimizeNone = 1 << 42,
}
}

Expand Down Expand Up @@ -2193,7 +2194,8 @@ pub fn ConstFCmp(pred: RealPredicate, v1: ValueRef, v2: ValueRef) -> ValueRef {

pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) {
unsafe {
LLVMAddFunctionAttribute(fn_, FunctionIndex as c_uint, attr.bits() as uint64_t)
LLVMAddFunctionAttribute(fn_, FunctionIndex as c_uint,
attr.bits() as uint64_t)
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/librustc_trans/trans/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,10 @@ pub fn LandingPad(cx: Block, ty: Type, pers_fn: ValueRef,
B(cx).landing_pad(ty, pers_fn, num_clauses, cx.fcx.llfn)
}

pub fn AddClause(cx: Block, landing_pad: ValueRef, clause: ValueRef) {
B(cx).add_clause(landing_pad, clause)
}

pub fn SetCleanup(cx: Block, landing_pad: ValueRef) {
B(cx).set_cleanup(landing_pad)
}
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_trans/trans/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) {
unsafe {
llvm::LLVMAddClause(landing_pad, clause);
}
}

pub fn set_cleanup(&self, landing_pad: ValueRef) {
self.count_insn("setcleanup");
unsafe {
Expand Down
17 changes: 9 additions & 8 deletions src/librustc_trans/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,16 +620,17 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}, ArgVals(args), dest)
}

/// This behemoth of a function translates function calls. Unfortunately, in order to generate more
/// efficient LLVM output at -O0, it has quite a complex signature (refactoring this into two
/// functions seems like a good idea).
/// This behemoth of a function translates function calls. Unfortunately, in
/// order to generate more efficient LLVM output at -O0, it has quite a complex
/// signature (refactoring this into two functions seems like a good idea).
///
/// In particular, for lang items, it is invoked with a dest of None, and in that case the return
/// value contains the result of the fn. The lang item must not return a structural type or else
/// all heck breaks loose.
/// In particular, for lang items, it is invoked with a dest of None, and in
/// that case the return value contains the result of the fn. The lang item must
/// not return a structural type or else all heck breaks loose.
///
/// For non-lang items, `dest` is always Some, and hence the result is written into memory
/// somewhere. Nonetheless we return the actual return value of the function.
/// For non-lang items, `dest` is always Some, and hence the result is written
/// into memory somewhere. Nonetheless we return the actual return value of the
/// function.
pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
debug_loc: DebugLoc,
get_callee: F,
Expand Down
52 changes: 2 additions & 50 deletions src/librustc_trans/trans/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,9 @@ pub use self::Heap::*;
use llvm::{BasicBlockRef, ValueRef};
use trans::base;
use trans::build;
use trans::callee;
use trans::common;
use trans::common::{Block, FunctionContext, ExprId, NodeIdAndSpan};
use trans::common::{Block, FunctionContext, NodeIdAndSpan};
use trans::debuginfo::{DebugLoc, ToDebugLoc};
use trans::declare;
use trans::glue;
use middle::region;
use trans::type_::Type;
Expand Down Expand Up @@ -833,53 +831,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
&[Type::i8p(self.ccx), Type::i32(self.ccx)],
false);

// The exception handling personality function.
//
// If our compilation unit has the `eh_personality` lang item somewhere
// within it, then we just need to translate that. Otherwise, we're
// building an rlib which will depend on some upstream implementation of
// this function, so we just codegen a generic reference to it. We don't
// specify any of the types for the function, we just make it a symbol
// that LLVM can later use.
//
// Note that MSVC is a little special here in that we don't use the
// `eh_personality` lang item at all. Currently LLVM has support for
// both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
// *name of the personality function* to decide what kind of unwind side
// tables/landing pads to emit. It looks like Dwarf is used by default,
// injecting a dependency on the `_Unwind_Resume` symbol for resuming
// an "exception", but for MSVC we want to force SEH. This means that we
// can't actually have the personality function be our standard
// `rust_eh_personality` function, but rather we wired it up to the
// CRT's custom personality function, which forces LLVM to consider
// landing pads as "landing pads for SEH".
let target = &self.ccx.sess().target.target;
let llpersonality = match pad_bcx.tcx().lang_items.eh_personality() {
Some(def_id) if !target.options.is_like_msvc => {
callee::trans_fn_ref(pad_bcx.ccx(), def_id, ExprId(0),
pad_bcx.fcx.param_substs).val
}
_ => {
let mut personality = self.ccx.eh_personality().borrow_mut();
match *personality {
Some(llpersonality) => llpersonality,
None => {
let name = if !target.options.is_like_msvc {
"rust_eh_personality"
} else if target.arch == "x86" {
"_except_handler3"
} else {
"__C_specific_handler"
};
let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
let f = declare::declare_cfn(self.ccx, name, fty,
self.ccx.tcx().types.i32);
*personality = Some(f);
f
}
}
}
};
let llpersonality = pad_bcx.fcx.eh_personality();

// The only landing pad clause will be 'cleanup'
let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1);
Expand Down
16 changes: 6 additions & 10 deletions src/librustc_trans/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,10 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
mangle_internal_name_by_path_and_seq(path, "closure")
});

// Currently there’s only a single user of get_or_create_declaration_if_closure and it
// unconditionally defines the function, therefore we use define_* here.
let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type).unwrap_or_else(||{
ccx.sess().bug(&format!("symbol `{}` already defined", symbol));
});
// Currently there’s only a single user of
// get_or_create_declaration_if_closure and it unconditionally defines the
// function, therefore we use define_* here.
let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type);

// set an inline hint for all closures
attributes::inline(llfn, attributes::InlineAttr::Hint);
Expand Down Expand Up @@ -388,11 +387,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(

// Create the by-value helper.
let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim");
let lloncefn = declare::define_internal_rust_fn(ccx, &function_name[..], llonce_fn_ty)
.unwrap_or_else(||{
ccx.sess().bug(&format!("symbol `{}` already defined", function_name));
});

let lloncefn = declare::define_internal_rust_fn(ccx, &function_name,
llonce_fn_ty);
let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig);
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
Expand Down
51 changes: 51 additions & 0 deletions src/librustc_trans/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use middle::lang_items::LangItem;
use middle::subst::{self, Substs};
use trans::base;
use trans::build;
use trans::callee;
use trans::cleanup;
use trans::consts;
use trans::datum;
Expand Down Expand Up @@ -479,6 +480,56 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
type_needs_drop_given_env(self.ccx.tcx(), ty, &self.param_env)
}

pub fn eh_personality(&self) -> ValueRef {
// The exception handling personality function.
//
// If our compilation unit has the `eh_personality` lang item somewhere
// within it, then we just need to translate that. Otherwise, we're
// building an rlib which will depend on some upstream implementation of
// this function, so we just codegen a generic reference to it. We don't
// specify any of the types for the function, we just make it a symbol
// that LLVM can later use.
//
// Note that MSVC is a little special here in that we don't use the
// `eh_personality` lang item at all. Currently LLVM has support for
// both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
// *name of the personality function* to decide what kind of unwind side
// tables/landing pads to emit. It looks like Dwarf is used by default,
// injecting a dependency on the `_Unwind_Resume` symbol for resuming
// an "exception", but for MSVC we want to force SEH. This means that we
// can't actually have the personality function be our standard
// `rust_eh_personality` function, but rather we wired it up to the
// CRT's custom personality function, which forces LLVM to consider
// landing pads as "landing pads for SEH".
let target = &self.ccx.sess().target.target;
match self.ccx.tcx().lang_items.eh_personality() {
Some(def_id) if !target.options.is_like_msvc => {
callee::trans_fn_ref(self.ccx, def_id, ExprId(0),
self.param_substs).val
}
_ => {
let mut personality = self.ccx.eh_personality().borrow_mut();
match *personality {
Some(llpersonality) => llpersonality,
None => {
let name = if !target.options.is_like_msvc {
"rust_eh_personality"
} else if target.arch == "x86" {
"_except_handler3"
} else {
"__C_specific_handler"
};
let fty = Type::variadic_func(&[], &Type::i32(self.ccx));
let f = declare::declare_cfn(self.ccx, name, fty,
self.ccx.tcx().types.i32);
*personality = Some(f);
f
}
}
}
}
}
}

// Basic block context. We create a block context for each basic block
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_trans/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pub struct LocalCrateContext<'tcx> {
dbg_cx: Option<debuginfo::CrateDebugContext<'tcx>>,

eh_personality: RefCell<Option<ValueRef>>,
rust_try_fn: RefCell<Option<ValueRef>>,

intrinsics: RefCell<FnvHashMap<&'static str, ValueRef>>,

Expand Down Expand Up @@ -461,6 +462,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
closure_vals: RefCell::new(FnvHashMap()),
dbg_cx: dbg_cx,
eh_personality: RefCell::new(None),
rust_try_fn: RefCell::new(None),
intrinsics: RefCell::new(FnvHashMap()),
n_llvm_insns: Cell::new(0),
trait_cache: RefCell::new(FnvHashMap()),
Expand Down Expand Up @@ -726,6 +728,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local.eh_personality
}

pub fn rust_try_fn<'a>(&'a self) -> &'a RefCell<Option<ValueRef>> {
&self.local.rust_try_fn
}

fn intrinsics<'a>(&'a self) -> &'a RefCell<FnvHashMap<&'static str, ValueRef>> {
&self.local.intrinsics
}
Expand Down Expand Up @@ -923,6 +929,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);

ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
ifn!("llvm.eh.typeid.for", fn(i8p) -> t_i32);

// Some intrinsics were introduced in later versions of LLVM, but they have
// fallbacks in libc or libm and such.
Expand Down
21 changes: 11 additions & 10 deletions src/librustc_trans/trans/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
/// return None if the name already has a definition associated with it. In that
/// case an error should be reported to the user, because it usually happens due
/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, fn_type: Type,
output: ty::FnOutput) -> Option<ValueRef> {
pub fn define_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv,
fn_type: Type, output: ty::FnOutput) -> Option<ValueRef> {
if get_defined_value(ccx, name).is_some() {
None
} else {
Expand Down Expand Up @@ -224,20 +224,21 @@ pub fn define_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
/// Declare a Rust function with an intention to define it.
///
/// Use this function when you intend to define a function. This function will
/// return None if the name already has a definition associated with it. In that
/// case an error should be reported to the user, because it usually happens due
/// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes).
pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
fn_type: ty::Ty<'tcx>) -> Option<ValueRef> {
/// return panic if the name already has a definition associated with it. This
/// can happen with #[no_mangle] or #[export_name], for example.
pub fn define_internal_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
name: &str,
fn_type: ty::Ty<'tcx>) -> ValueRef {
if get_defined_value(ccx, name).is_some() {
None
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
} else {
Some(declare_internal_rust_fn(ccx, name, fn_type))
declare_internal_rust_fn(ccx, name, fn_type)
}
}


/// Get defined or externally defined (AvailableExternally linkage) value by name.
/// Get defined or externally defined (AvailableExternally linkage) value by
/// name.
fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
debug!("get_defined_value(name={:?})", name);
let namebuf = CString::new(name).unwrap_or_else(|_|{
Expand Down
4 changes: 1 addition & 3 deletions src/librustc_trans/trans/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ccx.tcx().map.path_to_string(id),
id, t);

let llfn = declare::define_internal_rust_fn(ccx, &ps[..], t).unwrap_or_else(||{
ccx.sess().bug(&format!("symbol `{}` already defined", ps));
});
let llfn = declare::define_internal_rust_fn(ccx, &ps, t);
attributes::from_fn_attrs(ccx, attrs, llfn);
base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]);
llfn
Expand Down
Loading