Skip to content

Commit 5c1a70d

Browse files
committed
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
1 parent 746d086 commit 5c1a70d

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

src/libcore/failure.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,25 @@
2828
2929
#![allow(dead_code, missing_doc)]
3030

31-
#[cfg(not(test))]
32-
use str::raw::c_str_to_static_slice;
3331
use fmt;
32+
use intrinsics;
33+
#[cfg(not(test), stage0)]
34+
use str::raw::c_str_to_static_slice;
35+
36+
#[cold] #[inline(never)] // this is the slow path, always
37+
#[lang="fail_"]
38+
#[cfg(not(test), not(stage0))]
39+
fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! {
40+
format_args!(|args| -> () {
41+
begin_unwind(args, file, line);
42+
}, "{}", expr);
43+
44+
unsafe { intrinsics::abort() }
45+
}
3446

3547
#[cold] #[inline(never)] // this is the slow path, always
3648
#[lang="fail_"]
37-
#[cfg(not(test))]
49+
#[cfg(not(test), stage0)]
3850
fn fail_(expr: *u8, file: *u8, line: uint) -> ! {
3951
unsafe {
4052
let expr = c_str_to_static_slice(expr as *i8);
@@ -43,19 +55,30 @@ fn fail_(expr: *u8, file: *u8, line: uint) -> ! {
4355
begin_unwind(args, file, line);
4456
}, "{}", expr);
4557

46-
loop {}
58+
intrinsics::abort()
4759
}
4860
}
4961

5062
#[cold]
5163
#[lang="fail_bounds_check"]
52-
#[cfg(not(test))]
64+
#[cfg(not(test), not(stage0))]
65+
fn fail_bounds_check(file: &'static str, line: uint,
66+
index: uint, len: uint) -> ! {
67+
format_args!(|args| -> () {
68+
begin_unwind(args, file, line);
69+
}, "index out of bounds: the len is {} but the index is {}", len, index);
70+
unsafe { intrinsics::abort() }
71+
}
72+
73+
#[cold]
74+
#[lang="fail_bounds_check"]
75+
#[cfg(not(test), stage0)]
5376
fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) -> ! {
5477
let file = unsafe { c_str_to_static_slice(file as *i8) };
5578
format_args!(|args| -> () {
5679
begin_unwind(args, file, line);
5780
}, "index out of bounds: the len is {} but the index is {}", len, index);
58-
loop {}
81+
unsafe { intrinsics::abort() }
5982
}
6083

6184
#[cold]

src/librustc/middle/trans/common.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
596596
pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
597597
unsafe {
598598
let len = s.get().len();
599-
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false), Type::i8p(cx).to_ref());
599+
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
600+
Type::i8p(cx).to_ref());
600601
C_struct(cx, [cs, C_uint(cx, len)], false)
601602
}
602603
}
@@ -843,19 +844,6 @@ pub fn find_vtable(tcx: &ty::ctxt,
843844
param_bounds.get(n_bound).clone()
844845
}
845846

846-
pub fn filename_and_line_num_from_span(bcx: &Block, span: Span)
847-
-> (ValueRef, ValueRef) {
848-
let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
849-
let filename_cstr = C_cstr(bcx.ccx(),
850-
token::intern_and_get_ident(loc.file
851-
.name
852-
.as_slice()),
853-
true);
854-
let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx()));
855-
let line = C_int(bcx.ccx(), loc.line as int);
856-
(filename, line)
857-
}
858-
859847
// Casts a Rust bool value to an i1.
860848
pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
861849
build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))

src/librustc/middle/trans/controlflow.rs

+27-13
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,15 @@ use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
1414
use middle::trans::base::*;
1515
use middle::trans::build::*;
1616
use middle::trans::callee;
17+
use middle::trans::cleanup::CleanupMethods;
18+
use middle::trans::cleanup;
1719
use middle::trans::common::*;
1820
use middle::trans::debuginfo;
19-
use middle::trans::cleanup;
20-
use middle::trans::cleanup::CleanupMethods;
2121
use middle::trans::expr;
22+
use middle::trans::type_of;
2223
use middle::ty;
2324
use util::ppaux::Repr;
2425

25-
use middle::trans::type_::Type;
26-
2726
use syntax::ast;
2827
use syntax::ast::Ident;
2928
use syntax::ast_util;
@@ -337,23 +336,31 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>,
337336
return bcx;
338337
}
339338

339+
fn str_slice_arg<'a>(bcx: &'a Block<'a>, s: InternedString) -> ValueRef {
340+
let ccx = bcx.ccx();
341+
let t = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable);
342+
let s = C_str_slice(ccx, s);
343+
let slot = alloca(bcx, val_ty(s), "__temp");
344+
Store(bcx, s, slot);
345+
346+
// The type of C_str_slice is { i8*, i64 }, but the type of the &str is
347+
// %str_slice, so we do a bitcast here to the right type.
348+
BitCast(bcx, slot, type_of::type_of(ccx, t).ptr_to())
349+
}
350+
340351
pub fn trans_fail<'a>(
341352
bcx: &'a Block<'a>,
342353
sp: Span,
343354
fail_str: InternedString)
344355
-> &'a Block<'a> {
345356
let ccx = bcx.ccx();
346-
let v_fail_str = C_cstr(ccx, fail_str, true);
347357
let _icx = push_ctxt("trans_fail_value");
358+
359+
let v_str = str_slice_arg(bcx, fail_str);
348360
let loc = bcx.sess().codemap().lookup_char_pos(sp.lo);
349-
let v_filename = C_cstr(ccx,
350-
token::intern_and_get_ident(loc.file
351-
.name
352-
.as_slice()),
353-
true);
361+
let filename = token::intern_and_get_ident(loc.file.name.as_slice());
362+
let v_filename = str_slice_arg(bcx, filename);
354363
let v_line = loc.line as int;
355-
let v_str = PointerCast(bcx, v_fail_str, Type::i8p(ccx));
356-
let v_filename = PointerCast(bcx, v_filename, Type::i8p(ccx));
357364
let args = vec!(v_str, v_filename, C_int(ccx, v_line));
358365
let did = langcall(bcx, Some(sp), "", FailFnLangItem);
359366
let bcx = callee::trans_lang_call(bcx,
@@ -371,7 +378,14 @@ pub fn trans_fail_bounds_check<'a>(
371378
len: ValueRef)
372379
-> &'a Block<'a> {
373380
let _icx = push_ctxt("trans_fail_bounds_check");
374-
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
381+
382+
// Extract the file/line from the span
383+
let loc = bcx.sess().codemap().lookup_char_pos(sp.lo);
384+
let filename = token::intern_and_get_ident(loc.file.name.as_slice());
385+
386+
// Invoke the lang item
387+
let filename = str_slice_arg(bcx, filename);
388+
let line = C_int(bcx.ccx(), loc.line as int);
375389
let args = vec!(filename, line, index, len);
376390
let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem);
377391
let bcx = callee::trans_lang_call(bcx,

src/test/auxiliary/lang-item-public.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![no_std]
1212

1313
#[lang="fail_"]
14-
fn fail(_: *i8, _: *i8, _: uint) -> ! { loop {} }
14+
fn fail(_: &'static str, _: &'static str, _: uint) -> ! { loop {} }
1515

1616
#[lang = "stack_exhausted"]
1717
extern fn stack_exhausted() {}

0 commit comments

Comments
 (0)