From 5c1a70d49874ce3922af5cd3eeea7ae2dbc9db7e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 26 May 2014 10:33:18 -0700 Subject: [PATCH] rustc: Use rust strings for failure arguments This avoids having to perform conversions from `*u8` to `&'static str` which can suck in a good deal of code. Closes #14442 --- src/libcore/failure.rs | 35 +++++++++++++++++---- src/librustc/middle/trans/common.rs | 16 ++-------- src/librustc/middle/trans/controlflow.rs | 40 ++++++++++++++++-------- src/test/auxiliary/lang-item-public.rs | 2 +- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/libcore/failure.rs b/src/libcore/failure.rs index 003ebed6364..a53a380d737 100644 --- a/src/libcore/failure.rs +++ b/src/libcore/failure.rs @@ -28,13 +28,25 @@ #![allow(dead_code, missing_doc)] -#[cfg(not(test))] -use str::raw::c_str_to_static_slice; use fmt; +use intrinsics; +#[cfg(not(test), stage0)] +use str::raw::c_str_to_static_slice; #[cold] #[inline(never)] // this is the slow path, always #[lang="fail_"] -#[cfg(not(test))] +#[cfg(not(test), not(stage0))] +fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! { + format_args!(|args| -> () { + begin_unwind(args, file, line); + }, "{}", expr); + + unsafe { intrinsics::abort() } +} + +#[cold] #[inline(never)] // this is the slow path, always +#[lang="fail_"] +#[cfg(not(test), stage0)] fn fail_(expr: *u8, file: *u8, line: uint) -> ! { unsafe { let expr = c_str_to_static_slice(expr as *i8); @@ -43,19 +55,30 @@ fn fail_(expr: *u8, file: *u8, line: uint) -> ! { begin_unwind(args, file, line); }, "{}", expr); - loop {} + intrinsics::abort() } } #[cold] #[lang="fail_bounds_check"] -#[cfg(not(test))] +#[cfg(not(test), not(stage0))] +fn fail_bounds_check(file: &'static str, line: uint, + index: uint, len: uint) -> ! { + format_args!(|args| -> () { + begin_unwind(args, file, line); + }, "index out of bounds: the len is {} but the index is {}", len, index); + unsafe { intrinsics::abort() } +} + +#[cold] +#[lang="fail_bounds_check"] +#[cfg(not(test), stage0)] fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) -> ! { let file = unsafe { c_str_to_static_slice(file as *i8) }; format_args!(|args| -> () { begin_unwind(args, file, line); }, "index out of bounds: the len is {} but the index is {}", len, index); - loop {} + unsafe { intrinsics::abort() } } #[cold] diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 55638b9f80a..154a5eaa780 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -596,7 +596,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef { unsafe { let len = s.get().len(); - let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false), Type::i8p(cx).to_ref()); + let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false), + Type::i8p(cx).to_ref()); C_struct(cx, [cs, C_uint(cx, len)], false) } } @@ -843,19 +844,6 @@ pub fn find_vtable(tcx: &ty::ctxt, param_bounds.get(n_bound).clone() } -pub fn filename_and_line_num_from_span(bcx: &Block, span: Span) - -> (ValueRef, ValueRef) { - let loc = bcx.sess().codemap().lookup_char_pos(span.lo); - let filename_cstr = C_cstr(bcx.ccx(), - token::intern_and_get_ident(loc.file - .name - .as_slice()), - true); - let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx())); - let line = C_int(bcx.ccx(), loc.line as int); - (filename, line) -} - // Casts a Rust bool value to an i1. pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef { build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false)) diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 419b4f1e110..2174fe3df9a 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -14,16 +14,15 @@ use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem}; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee; +use middle::trans::cleanup::CleanupMethods; +use middle::trans::cleanup; use middle::trans::common::*; use middle::trans::debuginfo; -use middle::trans::cleanup; -use middle::trans::cleanup::CleanupMethods; use middle::trans::expr; +use middle::trans::type_of; use middle::ty; use util::ppaux::Repr; -use middle::trans::type_::Type; - use syntax::ast; use syntax::ast::Ident; use syntax::ast_util; @@ -337,23 +336,31 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>, return bcx; } +fn str_slice_arg<'a>(bcx: &'a Block<'a>, s: InternedString) -> ValueRef { + let ccx = bcx.ccx(); + let t = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable); + let s = C_str_slice(ccx, s); + let slot = alloca(bcx, val_ty(s), "__temp"); + Store(bcx, s, slot); + + // The type of C_str_slice is { i8*, i64 }, but the type of the &str is + // %str_slice, so we do a bitcast here to the right type. + BitCast(bcx, slot, type_of::type_of(ccx, t).ptr_to()) +} + pub fn trans_fail<'a>( bcx: &'a Block<'a>, sp: Span, fail_str: InternedString) -> &'a Block<'a> { let ccx = bcx.ccx(); - let v_fail_str = C_cstr(ccx, fail_str, true); let _icx = push_ctxt("trans_fail_value"); + + let v_str = str_slice_arg(bcx, fail_str); let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); - let v_filename = C_cstr(ccx, - token::intern_and_get_ident(loc.file - .name - .as_slice()), - true); + let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + let v_filename = str_slice_arg(bcx, filename); let v_line = loc.line as int; - let v_str = PointerCast(bcx, v_fail_str, Type::i8p(ccx)); - let v_filename = PointerCast(bcx, v_filename, Type::i8p(ccx)); let args = vec!(v_str, v_filename, C_int(ccx, v_line)); let did = langcall(bcx, Some(sp), "", FailFnLangItem); let bcx = callee::trans_lang_call(bcx, @@ -371,7 +378,14 @@ pub fn trans_fail_bounds_check<'a>( len: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("trans_fail_bounds_check"); - let (filename, line) = filename_and_line_num_from_span(bcx, sp); + + // Extract the file/line from the span + let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); + let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + + // Invoke the lang item + let filename = str_slice_arg(bcx, filename); + let line = C_int(bcx.ccx(), loc.line as int); let args = vec!(filename, line, index, len); let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 2c9a5bc433f..4b19d291b85 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -11,7 +11,7 @@ #![no_std] #[lang="fail_"] -fn fail(_: *i8, _: *i8, _: uint) -> ! { loop {} } +fn fail(_: &'static str, _: &'static str, _: uint) -> ! { loop {} } #[lang = "stack_exhausted"] extern fn stack_exhausted() {}