Skip to content

Commit

Permalink
rustc: Use rust strings for failure arguments
Browse files Browse the repository at this point in the history
This avoids having to perform conversions from `*u8` to `&'static str` which can
suck in a good deal of code.

Closes rust-lang#14442
  • Loading branch information
alexcrichton committed May 27, 2014
1 parent 746d086 commit 5c1a70d
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 34 deletions.
35 changes: 29 additions & 6 deletions src/libcore/failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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), 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))]
#[cfg(not(test), stage0)]
fn fail_(expr: *u8, file: *u8, line: uint) -> ! {
unsafe {
let expr = c_str_to_static_slice(expr as *i8);
Expand All @@ -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]
Expand Down
16 changes: 2 additions & 14 deletions src/librustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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))
Expand Down
40 changes: 27 additions & 13 deletions src/librustc/middle/trans/controlflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/test/auxiliary/lang-item-public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand Down

1 comment on commit 5c1a70d

@brson
Copy link

@brson brson commented on 5c1a70d May 29, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

Please sign in to comment.