Skip to content

rustc: Use rust strings for failure arguments #14451

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

Merged
merged 1 commit into from
May 29, 2014
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
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.
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to construct a %str_slice directly?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not that I could find easily, but I'm also quite unfamiliar with trans so I'm likely doing something wrong here...

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