2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
|
|
|
|
2013-02-25 13:11:21 -06:00
|
|
|
use back::link;
|
|
|
|
use lib;
|
|
|
|
use lib::llvm::*;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::trans::base::*;
|
2013-02-25 13:11:21 -06:00
|
|
|
use middle::trans::build::*;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::trans::callee;
|
2012-12-13 15:05:22 -06:00
|
|
|
use middle::trans::common::*;
|
2013-02-25 13:11:21 -06:00
|
|
|
use middle::trans::debuginfo;
|
|
|
|
use middle::trans::expr;
|
|
|
|
use middle::trans::type_of::*;
|
|
|
|
use middle::ty;
|
|
|
|
use util::common::indenter;
|
|
|
|
use util::ppaux;
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
use middle::trans::type_::Type;
|
|
|
|
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::str;
|
|
|
|
use core::vec;
|
2013-02-25 13:11:21 -06:00
|
|
|
use syntax::ast;
|
|
|
|
use syntax::ast::ident;
|
|
|
|
use syntax::ast_map::path_mod;
|
|
|
|
use syntax::ast_util;
|
|
|
|
use syntax::codemap::span;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-01-31 19:12:29 -06:00
|
|
|
pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_block");
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut bcx = bcx;
|
|
|
|
do block_locals(b) |local| {
|
|
|
|
bcx = alloc_local(bcx, local);
|
|
|
|
};
|
2013-06-21 07:29:53 -05:00
|
|
|
for b.node.stmts.iter().advance |s| {
|
2012-08-28 17:54:45 -05:00
|
|
|
debuginfo::update_source_pos(bcx, b.span);
|
2013-04-17 11:15:37 -05:00
|
|
|
bcx = trans_stmt(bcx, *s);
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
match b.node.expr {
|
|
|
|
Some(e) => {
|
|
|
|
debuginfo::update_source_pos(bcx, e.span);
|
|
|
|
bcx = expr::trans_into(bcx, e, dest);
|
|
|
|
}
|
|
|
|
None => {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(dest == expr::Ignore || bcx.unreachable);
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return bcx;
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_if(bcx: block,
|
2012-08-28 17:54:45 -05:00
|
|
|
cond: @ast::expr,
|
2013-01-31 19:12:29 -06:00
|
|
|
thn: &ast::blk,
|
2012-08-28 17:54:45 -05:00
|
|
|
els: Option<@ast::expr>,
|
|
|
|
dest: expr::Dest)
|
2013-01-29 19:57:02 -06:00
|
|
|
-> block {
|
2012-08-28 17:54:45 -05:00
|
|
|
debug!("trans_if(bcx=%s, cond=%s, thn=%?, dest=%s)",
|
|
|
|
bcx.to_str(), bcx.expr_to_str(cond), thn.node.id,
|
|
|
|
dest.to_str(bcx.ccx()));
|
|
|
|
let _indenter = indenter();
|
|
|
|
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_if");
|
2012-08-28 17:54:45 -05:00
|
|
|
let Result {bcx, val: cond_val} =
|
2012-09-11 23:25:01 -05:00
|
|
|
expr::trans_to_datum(bcx, cond).to_result();
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-05-02 03:16:07 -05:00
|
|
|
let then_bcx_in = scope_block(bcx, thn.info(), "then");
|
|
|
|
let else_bcx_in = scope_block(bcx, els.info(), "else");
|
2013-02-06 16:28:02 -06:00
|
|
|
|
|
|
|
let cond_val = bool_to_i1(bcx, cond_val);
|
2012-08-28 17:54:45 -05:00
|
|
|
CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb);
|
|
|
|
|
|
|
|
debug!("then_bcx_in=%s, else_bcx_in=%s",
|
|
|
|
then_bcx_in.to_str(), else_bcx_in.to_str());
|
|
|
|
|
|
|
|
let then_bcx_out = trans_block(then_bcx_in, thn, dest);
|
|
|
|
let then_bcx_out = trans_block_cleanups(then_bcx_out,
|
|
|
|
block_cleanups(then_bcx_in));
|
|
|
|
|
|
|
|
// Calling trans_block directly instead of trans_expr
|
|
|
|
// because trans_expr will create another scope block
|
|
|
|
// context for the block, but we've already got the
|
|
|
|
// 'else' context
|
|
|
|
let else_bcx_out = match els {
|
|
|
|
Some(elexpr) => {
|
|
|
|
match elexpr.node {
|
|
|
|
ast::expr_if(_, _, _) => {
|
|
|
|
let elseif_blk = ast_util::block_from_expr(elexpr);
|
2013-01-31 19:12:29 -06:00
|
|
|
trans_block(else_bcx_in, &elseif_blk, dest)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2012-12-04 12:50:00 -06:00
|
|
|
ast::expr_block(ref blk) => {
|
2013-01-31 19:12:29 -06:00
|
|
|
trans_block(else_bcx_in, blk, dest)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
// would be nice to have a constraint on ifs
|
2013-05-19 00:07:44 -05:00
|
|
|
_ => bcx.tcx().sess.bug("strange alternative in if")
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => else_bcx_in
|
|
|
|
};
|
|
|
|
let else_bcx_out = trans_block_cleanups(else_bcx_out,
|
|
|
|
block_cleanups(else_bcx_in));
|
2013-05-19 00:07:44 -05:00
|
|
|
return join_blocks(bcx, [then_bcx_out, else_bcx_out]);
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
|
2013-05-02 03:16:07 -05:00
|
|
|
let out = sub_block(parent_bcx, "join");
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut reachable = false;
|
2013-06-21 07:29:53 -05:00
|
|
|
for in_cxs.iter().advance |bcx| {
|
2012-08-28 17:54:45 -05:00
|
|
|
if !bcx.unreachable {
|
2012-09-18 23:41:37 -05:00
|
|
|
Br(*bcx, out.llbb);
|
2012-08-28 17:54:45 -05:00
|
|
|
reachable = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reachable {
|
|
|
|
Unreachable(out);
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-01-31 19:12:29 -06:00
|
|
|
pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::blk) -> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_while");
|
2013-05-02 03:16:07 -05:00
|
|
|
let next_bcx = sub_block(bcx, "while next");
|
2012-08-28 17:54:45 -05:00
|
|
|
|
|
|
|
// bcx
|
|
|
|
// |
|
|
|
|
// loop_bcx
|
|
|
|
// |
|
|
|
|
// cond_bcx_in <--------+
|
|
|
|
// | |
|
|
|
|
// cond_bcx_out |
|
|
|
|
// | | |
|
|
|
|
// | body_bcx_in |
|
|
|
|
// +------+ | |
|
|
|
|
// | body_bcx_out --+
|
|
|
|
// next_bcx
|
|
|
|
|
2013-05-02 03:16:07 -05:00
|
|
|
let loop_bcx = loop_scope_block(bcx, next_bcx, None, "`while`",
|
2012-10-18 14:20:18 -05:00
|
|
|
body.info());
|
2013-05-02 03:16:07 -05:00
|
|
|
let cond_bcx_in = scope_block(loop_bcx, cond.info(), "while loop cond");
|
|
|
|
let body_bcx_in = scope_block(loop_bcx, body.info(), "while loop body");
|
2012-08-28 17:54:45 -05:00
|
|
|
Br(bcx, loop_bcx.llbb);
|
|
|
|
Br(loop_bcx, cond_bcx_in.llbb);
|
|
|
|
|
|
|
|
// compile the condition
|
|
|
|
let Result {bcx: cond_bcx_out, val: cond_val} =
|
2012-09-11 23:25:01 -05:00
|
|
|
expr::trans_to_datum(cond_bcx_in, cond).to_result();
|
2013-02-06 16:28:02 -06:00
|
|
|
let cond_val = bool_to_i1(cond_bcx_out, cond_val);
|
2012-08-28 17:54:45 -05:00
|
|
|
let cond_bcx_out =
|
|
|
|
trans_block_cleanups(cond_bcx_out, block_cleanups(cond_bcx_in));
|
|
|
|
CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, next_bcx.llbb);
|
|
|
|
|
|
|
|
// loop body:
|
|
|
|
let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore);
|
|
|
|
cleanup_and_Br(body_bcx_out, body_bcx_in, cond_bcx_in.llbb);
|
|
|
|
|
|
|
|
return next_bcx;
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_loop(bcx:block,
|
2013-01-31 19:12:29 -06:00
|
|
|
body: &ast::blk,
|
2013-01-29 19:57:02 -06:00
|
|
|
opt_label: Option<ident>)
|
|
|
|
-> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_loop");
|
2013-05-02 03:16:07 -05:00
|
|
|
let next_bcx = sub_block(bcx, "next");
|
|
|
|
let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
|
2012-10-18 14:20:18 -05:00
|
|
|
body.info());
|
2012-08-28 17:54:45 -05:00
|
|
|
Br(bcx, body_bcx_in.llbb);
|
|
|
|
let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore);
|
|
|
|
cleanup_and_Br(body_bcx_out, body_bcx_in, body_bcx_in.llbb);
|
|
|
|
return next_bcx;
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_log(log_ex: @ast::expr,
|
|
|
|
lvl: @ast::expr,
|
|
|
|
bcx: block,
|
|
|
|
e: @ast::expr) -> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_log");
|
2012-08-28 17:54:45 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
let mut bcx = bcx;
|
|
|
|
if ty::type_is_bot(expr_ty(bcx, lvl)) {
|
|
|
|
return expr::trans_into(bcx, lvl, expr::Ignore);
|
|
|
|
}
|
|
|
|
|
2013-03-16 13:11:31 -05:00
|
|
|
let (modpath, modname) = {
|
|
|
|
let path = &mut bcx.fcx.path;
|
|
|
|
let modpath = vec::append(
|
2013-05-02 03:16:07 -05:00
|
|
|
~[path_mod(ccx.sess.ident_of(ccx.link_meta.name))],
|
2013-03-16 13:11:31 -05:00
|
|
|
path.filtered(|e| match *e { path_mod(_) => true, _ => false }));
|
|
|
|
let modname = path_str(ccx.sess, modpath);
|
|
|
|
(modpath, modname)
|
|
|
|
};
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-02-08 16:08:02 -06:00
|
|
|
let global = if ccx.module_data.contains_key(&modname) {
|
2013-05-05 11:17:59 -05:00
|
|
|
ccx.module_data.get_copy(&modname)
|
2012-08-28 17:54:45 -05:00
|
|
|
} else {
|
2012-09-18 13:46:39 -05:00
|
|
|
let s = link::mangle_internal_name_by_path_and_seq(
|
2013-05-02 03:16:07 -05:00
|
|
|
ccx, modpath, "loglevel");
|
2013-01-10 23:23:07 -06:00
|
|
|
let global;
|
|
|
|
unsafe {
|
|
|
|
global = str::as_c_str(s, |buf| {
|
2013-06-16 05:52:44 -05:00
|
|
|
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
|
2013-01-10 23:23:07 -06:00
|
|
|
});
|
|
|
|
llvm::LLVMSetGlobalConstant(global, False);
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMSetInitializer(global, C_null(Type::i32()));
|
2013-01-10 23:23:07 -06:00
|
|
|
lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
|
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
ccx.module_data.insert(modname, global);
|
|
|
|
global
|
|
|
|
};
|
|
|
|
let current_level = Load(bcx, global);
|
|
|
|
let level = unpack_result!(bcx, {
|
2013-05-02 03:16:07 -05:00
|
|
|
do with_scope_result(bcx, lvl.info(), "level") |bcx| {
|
2012-09-11 23:25:01 -05:00
|
|
|
expr::trans_to_datum(bcx, lvl).to_result()
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let llenabled = ICmp(bcx, lib::llvm::IntUGE, current_level, level);
|
|
|
|
do with_cond(bcx, llenabled) |bcx| {
|
2013-05-02 03:16:07 -05:00
|
|
|
do with_scope(bcx, log_ex.info(), "log") |bcx| {
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut bcx = bcx;
|
|
|
|
|
|
|
|
// Translate the value to be logged
|
|
|
|
let val_datum = unpack_datum!(bcx, expr::trans_to_datum(bcx, e));
|
|
|
|
|
|
|
|
// Call the polymorphic log function
|
|
|
|
let val = val_datum.to_ref_llval(bcx);
|
2013-01-06 14:05:34 -06:00
|
|
|
let did = bcx.tcx().lang_items.log_type_fn();
|
2013-02-27 20:34:04 -06:00
|
|
|
let bcx = callee::trans_lang_call_with_type_params(
|
2013-05-19 00:07:44 -05:00
|
|
|
bcx, did, [level, val], [val_datum.ty], expr::Ignore);
|
2012-08-28 17:54:45 -05:00
|
|
|
bcx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_break_cont(bcx: block,
|
|
|
|
opt_label: Option<ident>,
|
|
|
|
to_end: bool)
|
|
|
|
-> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_break_cont");
|
2012-08-28 17:54:45 -05:00
|
|
|
// Locate closest loop block, outputting cleanup as we go.
|
|
|
|
let mut unwind = bcx;
|
|
|
|
let mut target;
|
|
|
|
loop {
|
2013-05-02 20:15:36 -05:00
|
|
|
match unwind.kind {
|
|
|
|
block_scope(@scope_info {
|
2013-01-06 13:16:14 -06:00
|
|
|
loop_break: Some(brk),
|
|
|
|
loop_label: l,
|
|
|
|
_
|
|
|
|
}) => {
|
2012-10-18 14:20:18 -05:00
|
|
|
// If we're looking for a labeled loop, check the label...
|
2012-10-22 11:44:56 -05:00
|
|
|
target = if to_end {
|
|
|
|
brk
|
|
|
|
} else {
|
|
|
|
unwind
|
|
|
|
};
|
2012-10-18 14:20:18 -05:00
|
|
|
match opt_label {
|
|
|
|
Some(desired) => match l {
|
|
|
|
Some(actual) if actual == desired => break,
|
|
|
|
// If it doesn't match the one we want,
|
|
|
|
// don't break
|
|
|
|
_ => ()
|
|
|
|
},
|
|
|
|
None => break
|
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
unwind = match unwind.parent {
|
|
|
|
Some(bcx) => bcx,
|
|
|
|
// This is a return from a loop body block
|
|
|
|
None => {
|
2013-04-18 17:53:29 -05:00
|
|
|
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
|
2012-08-28 17:54:45 -05:00
|
|
|
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
|
|
|
Unreachable(bcx);
|
|
|
|
return bcx;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
cleanup_and_Br(bcx, unwind, target.llbb);
|
|
|
|
Unreachable(bcx);
|
|
|
|
return bcx;
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_break(bcx: block, label_opt: Option<ident>) -> block {
|
2012-10-18 14:20:18 -05:00
|
|
|
return trans_break_cont(bcx, label_opt, true);
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_cont(bcx: block, label_opt: Option<ident>) -> block {
|
2012-10-18 14:20:18 -05:00
|
|
|
return trans_break_cont(bcx, label_opt, false);
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_ret");
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut bcx = bcx;
|
2013-06-20 09:42:44 -05:00
|
|
|
let dest = match copy bcx.fcx.loop_ret {
|
2013-02-19 01:40:42 -06:00
|
|
|
Some((flagptr, retptr)) => {
|
2012-08-28 17:54:45 -05:00
|
|
|
// This is a loop body return. Must set continue flag (our retptr)
|
|
|
|
// to false, return flag to true, and then store the value in the
|
|
|
|
// parent's retptr.
|
|
|
|
Store(bcx, C_bool(true), flagptr);
|
2013-04-18 17:53:29 -05:00
|
|
|
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
2013-06-20 09:42:44 -05:00
|
|
|
expr::SaveIn(match e {
|
2012-08-28 17:54:45 -05:00
|
|
|
Some(x) => PointerCast(bcx, retptr,
|
2013-06-15 22:45:48 -05:00
|
|
|
type_of(bcx.ccx(), expr_ty(bcx, x)).ptr_to()),
|
2012-08-28 17:54:45 -05:00
|
|
|
None => retptr
|
2013-06-20 09:42:44 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
None => match bcx.fcx.llretptr {
|
|
|
|
None => expr::Ignore,
|
|
|
|
Some(retptr) => expr::SaveIn(retptr),
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
match e {
|
|
|
|
Some(x) => {
|
2013-06-20 09:42:44 -05:00
|
|
|
bcx = expr::trans_into(bcx, x, dest);
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
|
|
|
|
Unreachable(bcx);
|
|
|
|
return bcx;
|
|
|
|
}
|
2013-01-29 19:57:02 -06:00
|
|
|
|
|
|
|
pub fn trans_fail_expr(bcx: block,
|
|
|
|
sp_opt: Option<span>,
|
|
|
|
fail_expr: Option<@ast::expr>)
|
|
|
|
-> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_fail_expr");
|
2012-08-28 17:54:45 -05:00
|
|
|
let mut bcx = bcx;
|
|
|
|
match fail_expr {
|
|
|
|
Some(arg_expr) => {
|
2013-06-04 23:43:41 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
let tcx = ccx.tcx;
|
2012-08-28 17:54:45 -05:00
|
|
|
let arg_datum = unpack_datum!(
|
|
|
|
bcx, expr::trans_to_datum(bcx, arg_expr));
|
|
|
|
|
|
|
|
if ty::type_is_str(arg_datum.ty) {
|
2013-05-03 15:26:43 -05:00
|
|
|
let (lldata, _) = arg_datum.get_vec_base_and_len_no_root(bcx);
|
2012-08-28 17:54:45 -05:00
|
|
|
return trans_fail_value(bcx, sp_opt, lldata);
|
|
|
|
} else if bcx.unreachable || ty::type_is_bot(arg_datum.ty) {
|
|
|
|
return bcx;
|
|
|
|
} else {
|
|
|
|
bcx.sess().span_bug(
|
|
|
|
arg_expr.span, ~"fail called with unsupported type " +
|
|
|
|
ppaux::ty_to_str(tcx, arg_datum.ty));
|
|
|
|
}
|
|
|
|
}
|
2013-06-12 12:02:55 -05:00
|
|
|
_ => trans_fail(bcx, sp_opt, @"explicit failure")
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_fail(bcx: block,
|
|
|
|
sp_opt: Option<span>,
|
2013-06-12 12:02:55 -05:00
|
|
|
fail_str: @str)
|
2013-01-29 19:57:02 -06:00
|
|
|
-> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_fail");
|
2012-08-28 17:54:45 -05:00
|
|
|
let V_fail_str = C_cstr(bcx.ccx(), fail_str);
|
|
|
|
return trans_fail_value(bcx, sp_opt, V_fail_str);
|
|
|
|
}
|
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
fn trans_fail_value(bcx: block,
|
|
|
|
sp_opt: Option<span>,
|
|
|
|
V_fail_str: ValueRef)
|
|
|
|
-> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_fail_value");
|
2012-08-28 17:54:45 -05:00
|
|
|
let ccx = bcx.ccx();
|
2013-02-19 01:40:42 -06:00
|
|
|
let (V_filename, V_line) = match sp_opt {
|
2012-08-28 17:54:45 -05:00
|
|
|
Some(sp) => {
|
|
|
|
let sess = bcx.sess();
|
2012-11-12 20:24:56 -06:00
|
|
|
let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo);
|
2013-06-12 12:02:55 -05:00
|
|
|
(C_cstr(bcx.ccx(), loc.file.name),
|
2013-02-20 18:41:21 -06:00
|
|
|
loc.line as int)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
None => {
|
2013-06-12 12:02:55 -05:00
|
|
|
(C_cstr(bcx.ccx(), @"<runtime>"), 0)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
};
|
2013-06-15 22:45:48 -05:00
|
|
|
let V_str = PointerCast(bcx, V_fail_str, Type::i8p());
|
|
|
|
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
|
2012-08-28 17:54:45 -05:00
|
|
|
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
|
2013-02-27 20:34:04 -06:00
|
|
|
let bcx = callee::trans_lang_call(
|
2013-01-07 14:21:34 -06:00
|
|
|
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
|
2012-08-28 17:54:45 -05:00
|
|
|
Unreachable(bcx);
|
|
|
|
return bcx;
|
|
|
|
}
|
2012-09-29 06:34:11 -05:00
|
|
|
|
2013-01-29 19:57:02 -06:00
|
|
|
pub fn trans_fail_bounds_check(bcx: block, sp: span,
|
|
|
|
index: ValueRef, len: ValueRef) -> block {
|
2013-06-16 23:23:24 -05:00
|
|
|
let _icx = push_ctxt("trans_fail_bounds_check");
|
2013-05-04 13:29:32 -05:00
|
|
|
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
|
2012-09-29 06:34:11 -05:00
|
|
|
let args = ~[filename, line, index, len];
|
2013-02-27 20:34:04 -06:00
|
|
|
let bcx = callee::trans_lang_call(
|
2013-01-07 14:21:34 -06:00
|
|
|
bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore);
|
2012-09-29 06:34:11 -05:00
|
|
|
Unreachable(bcx);
|
|
|
|
return bcx;
|
|
|
|
}
|