Change trans::common::block to be a class
And replace trans::common::block_parent with option<block>. To handle the recursive self-reference in the block_ class, I had to add a newtype-like enum "block" which is equivalent to @block_ -- which due to an interaction with borrowck, resulted in having to change a few functions in trans::base to take their block argument in ++ mode, irritatingly enough (but not that irritatingly, since we're supposed to get rid of modes).
This commit is contained in:
parent
d1ec1d4abb
commit
72360970fc
@ -50,6 +50,7 @@ import type_of::type_of; // Issue #1873
|
||||
import syntax::ast_map::{path, path_mod, path_name};
|
||||
|
||||
import std::smallintmap;
|
||||
import option::is_none;
|
||||
|
||||
// Destinations
|
||||
|
||||
@ -1207,7 +1208,8 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
|
||||
}
|
||||
}
|
||||
|
||||
fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
|
||||
// See [Note-arg-mode]
|
||||
fn call_tydesc_glue_full(++cx: block, v: ValueRef, tydesc: ValueRef,
|
||||
field: uint, static_ti: option<@tydesc_info>) {
|
||||
let _icx = cx.insn_ctxt("call_tydesc_glue_full");
|
||||
lazily_emit_tydesc_glue(cx.ccx(), field, static_ti);
|
||||
@ -1245,8 +1247,9 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
|
||||
C_null(T_ptr(T_ptr(cx.ccx().tydesc_type))), llrawptr]);
|
||||
}
|
||||
|
||||
fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint) ->
|
||||
block {
|
||||
// See [Note-arg-mode]
|
||||
fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint)
|
||||
-> block {
|
||||
let _icx = cx.insn_ctxt("call_tydesc_glue");
|
||||
let mut ti = none;
|
||||
let td = get_tydesc(cx.ccx(), t, ti);
|
||||
@ -3111,8 +3114,9 @@ fn body_contains_ret(body: ast::blk) -> bool {
|
||||
cx.found
|
||||
}
|
||||
|
||||
// See [Note-arg-mode]
|
||||
fn trans_call_inner(
|
||||
in_cx: block,
|
||||
++in_cx: block,
|
||||
call_info: option<node_info>,
|
||||
fn_expr_ty: ty::t,
|
||||
ret_ty: ty::t,
|
||||
@ -3240,8 +3244,8 @@ fn need_invoke(bcx: block) -> bool {
|
||||
_ { }
|
||||
}
|
||||
cur = alt cur.parent {
|
||||
parent_some(next) { next }
|
||||
parent_none { ret false; }
|
||||
some(next) { next }
|
||||
none { ret false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3262,7 +3266,7 @@ fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
|
||||
loop {
|
||||
alt bcx.kind {
|
||||
block_scope(inf) {
|
||||
if inf.cleanups.len() > 0u || bcx.parent == parent_none {
|
||||
if inf.cleanups.len() > 0u || is_none(bcx.parent) {
|
||||
f(inf); ret;
|
||||
}
|
||||
}
|
||||
@ -3471,11 +3475,11 @@ fn add_root_cleanup(bcx: block, scope_id: ast::node_id,
|
||||
some({id, _}) if id == scope_id { ret bcx_sid; }
|
||||
_ {
|
||||
alt bcx_sid.parent {
|
||||
parent_none {
|
||||
none {
|
||||
bcx.tcx().sess.bug(
|
||||
#fmt["no enclosing scope with id %d", scope_id]);
|
||||
}
|
||||
parent_some(bcx_par) { bcx_par }
|
||||
some(bcx_par) { bcx_par }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3785,7 +3789,10 @@ fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
|
||||
|
||||
// Since this function does *not* root, it is the caller's responsibility to
|
||||
// ensure that the referent is pointed to by a root.
|
||||
fn do_spill_noroot(cx: block, v: ValueRef) -> ValueRef {
|
||||
// [Note-arg-mode]
|
||||
// ++ mode is temporary, due to how borrowck treats enums. With hope,
|
||||
// will go away anyway when we get rid of modes.
|
||||
fn do_spill_noroot(++cx: block, v: ValueRef) -> ValueRef {
|
||||
let llptr = alloca(cx, val_ty(v));
|
||||
Store(cx, v, llptr);
|
||||
ret llptr;
|
||||
@ -3970,9 +3977,9 @@ fn trans_break_cont(bcx: block, to_end: bool)
|
||||
_ {}
|
||||
}
|
||||
unwind = alt unwind.parent {
|
||||
parent_some(cx) { cx }
|
||||
some(cx) { cx }
|
||||
// This is a return from a loop body block
|
||||
parent_none {
|
||||
none {
|
||||
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr);
|
||||
cleanup_and_leave(bcx, none, some(bcx.fcx.llreturn));
|
||||
Unreachable(bcx);
|
||||
@ -4090,7 +4097,7 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
|
||||
|
||||
// You probably don't want to use this one. See the
|
||||
// next three functions instead.
|
||||
fn new_block(cx: fn_ctxt, parent: block_parent, +kind: block_kind,
|
||||
fn new_block(cx: fn_ctxt, parent: option<block>, +kind: block_kind,
|
||||
name: str, opt_node_info: option<node_info>) -> block {
|
||||
|
||||
let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
|
||||
@ -4099,19 +4106,10 @@ fn new_block(cx: fn_ctxt, parent: block_parent, +kind: block_kind,
|
||||
let llbb: BasicBlockRef = str::as_c_str(s, {|buf|
|
||||
llvm::LLVMAppendBasicBlock(cx.llfn, buf)
|
||||
});
|
||||
let bcx = @{llbb: llbb,
|
||||
mut terminated: false,
|
||||
mut unreachable: false,
|
||||
parent: parent,
|
||||
kind: kind,
|
||||
node_info: opt_node_info,
|
||||
fcx: cx};
|
||||
alt parent {
|
||||
parent_some(cx) {
|
||||
let bcx = mk_block(llbb, parent, kind, opt_node_info, cx);
|
||||
option::iter(parent) {|cx|
|
||||
if cx.unreachable { Unreachable(bcx); }
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
};
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
@ -4122,20 +4120,20 @@ fn simple_block_scope() -> block_kind {
|
||||
|
||||
// Use this when you're at the top block of a function or the like.
|
||||
fn top_scope_block(fcx: fn_ctxt, opt_node_info: option<node_info>) -> block {
|
||||
ret new_block(fcx, parent_none, simple_block_scope(),
|
||||
ret new_block(fcx, none, simple_block_scope(),
|
||||
"function top level", opt_node_info);
|
||||
}
|
||||
|
||||
fn scope_block(bcx: block,
|
||||
opt_node_info: option<node_info>,
|
||||
n: str) -> block {
|
||||
ret new_block(bcx.fcx, parent_some(bcx), simple_block_scope(),
|
||||
ret new_block(bcx.fcx, some(bcx), simple_block_scope(),
|
||||
n, opt_node_info);
|
||||
}
|
||||
|
||||
fn loop_scope_block(bcx: block, loop_break: block, n: str,
|
||||
opt_node_info: option<node_info>) -> block {
|
||||
ret new_block(bcx.fcx, parent_some(bcx), block_scope({
|
||||
ret new_block(bcx.fcx, some(bcx), block_scope({
|
||||
loop_break: some(loop_break),
|
||||
mut cleanups: [],
|
||||
mut cleanup_paths: [],
|
||||
@ -4146,17 +4144,11 @@ fn loop_scope_block(bcx: block, loop_break: block, n: str,
|
||||
|
||||
// Use this when you're making a general CFG BB within a scope.
|
||||
fn sub_block(bcx: block, n: str) -> block {
|
||||
ret new_block(bcx.fcx, parent_some(bcx), block_non_scope, n, none);
|
||||
new_block(bcx.fcx, some(bcx), block_non_scope, n, none)
|
||||
}
|
||||
|
||||
fn raw_block(fcx: fn_ctxt, llbb: BasicBlockRef) -> block {
|
||||
ret @{llbb: llbb,
|
||||
mut terminated: false,
|
||||
mut unreachable: false,
|
||||
parent: parent_none,
|
||||
kind: block_non_scope,
|
||||
node_info: none,
|
||||
fcx: fcx};
|
||||
mk_block(llbb, none, block_non_scope, none, fcx)
|
||||
}
|
||||
|
||||
|
||||
@ -4231,8 +4223,8 @@ fn cleanup_and_leave(bcx: block, upto: option<BasicBlockRef>,
|
||||
_ {}
|
||||
}
|
||||
cur = alt cur.parent {
|
||||
parent_some(next) { next }
|
||||
parent_none { assert option::is_none(upto); break; }
|
||||
some(next) { next }
|
||||
none { assert is_none(upto); break; }
|
||||
};
|
||||
}
|
||||
alt leave {
|
||||
|
@ -350,32 +350,44 @@ type node_info = {
|
||||
// code. Each basic block we generate is attached to a function, typically
|
||||
// with many basic blocks per function. All the basic blocks attached to a
|
||||
// function are organized as a directed graph.
|
||||
type block = @{
|
||||
class block_ {
|
||||
// The BasicBlockRef returned from a call to
|
||||
// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
|
||||
// block to the function pointed to by llfn. We insert
|
||||
// instructions into that block by way of this block context.
|
||||
// The block pointing to this one in the function's digraph.
|
||||
llbb: BasicBlockRef,
|
||||
mut terminated: bool,
|
||||
mut unreachable: bool,
|
||||
parent: block_parent,
|
||||
let llbb: BasicBlockRef;
|
||||
let mut terminated: bool;
|
||||
let mut unreachable: bool;
|
||||
let parent: option<block>;
|
||||
// The 'kind' of basic block this is.
|
||||
kind: block_kind,
|
||||
let kind: block_kind;
|
||||
// info about the AST node this block originated from, if any
|
||||
node_info: option<node_info>,
|
||||
let node_info: option<node_info>;
|
||||
// The function context for the function to which this block is
|
||||
// attached.
|
||||
fcx: fn_ctxt
|
||||
};
|
||||
let fcx: fn_ctxt;
|
||||
new(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
|
||||
node_info: option<node_info>, fcx: fn_ctxt) {
|
||||
// sigh
|
||||
self.llbb = llbb; self.terminated = false; self.unreachable = false;
|
||||
self.parent = parent; self.kind = kind; self.node_info = node_info;
|
||||
self.fcx = fcx;
|
||||
}
|
||||
}
|
||||
|
||||
/* This must be enum and not type, or trans goes into an infinite loop (#2572)
|
||||
*/
|
||||
enum block = @block_;
|
||||
|
||||
fn mk_block(llbb: BasicBlockRef, parent: option<block>, -kind: block_kind,
|
||||
node_info: option<node_info>, fcx: fn_ctxt) -> block {
|
||||
block(@block_(llbb, parent, kind, node_info, fcx))
|
||||
}
|
||||
|
||||
// First two args are retptr, env
|
||||
const first_real_arg: uint = 2u;
|
||||
|
||||
// FIXME move blocks to a class once those are finished, and simply use
|
||||
// option<block> for this. (#2532)
|
||||
enum block_parent { parent_none, parent_some(block), }
|
||||
|
||||
type result = {bcx: block, val: ValueRef};
|
||||
type result_t = {bcx: block, val: ValueRef, ty: ty::t};
|
||||
|
||||
@ -412,7 +424,11 @@ fn in_scope_cx(cx: block, f: fn(scope_info)) {
|
||||
}
|
||||
|
||||
fn block_parent(cx: block) -> block {
|
||||
alt check cx.parent { parent_some(b) { b } }
|
||||
alt cx.parent {
|
||||
some(b) { b }
|
||||
none { cx.sess().bug(#fmt("block_parent called on root block %?",
|
||||
cx)); }
|
||||
}
|
||||
}
|
||||
|
||||
// Accessors
|
||||
|
@ -236,8 +236,8 @@ fn create_block(cx: block) -> @metadata<block_md> {
|
||||
let mut cx = cx;
|
||||
while option::is_none(cx.node_info) {
|
||||
alt cx.parent {
|
||||
parent_some(b) { cx = b; }
|
||||
parent_none { fail; }
|
||||
some(b) { cx = b; }
|
||||
none { fail; }
|
||||
}
|
||||
}
|
||||
let sp = option::get(cx.node_info).span;
|
||||
@ -254,8 +254,8 @@ fn create_block(cx: block) -> @metadata<block_md> {
|
||||
}*/
|
||||
|
||||
let parent = alt cx.parent {
|
||||
parent_none { create_function(cx.fcx).node }
|
||||
parent_some(bcx) { create_block(bcx).node }
|
||||
none { create_function(cx.fcx).node }
|
||||
some(bcx) { create_block(bcx).node }
|
||||
};
|
||||
let file_node = create_file(cx.ccx(), fname);
|
||||
let unique_id = alt cache.find(LexicalBlockTag) {
|
||||
@ -658,8 +658,8 @@ fn create_local_var(bcx: block, local: @ast::local)
|
||||
let tymd = create_ty(cx, ty, local.node.ty);
|
||||
let filemd = create_file(cx, loc.file.name);
|
||||
let context = alt bcx.parent {
|
||||
parent_none { create_function(bcx.fcx).node }
|
||||
parent_some(_) { create_block(bcx).node }
|
||||
none { create_function(bcx.fcx).node }
|
||||
some(_) { create_block(bcx).node }
|
||||
};
|
||||
let mdnode = create_var(tg, context, name, filemd.node,
|
||||
loc.line as int, tymd.node);
|
||||
@ -761,9 +761,10 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
|
||||
(nm, decl.output, ctor_id)
|
||||
}
|
||||
ast_map::class_ctor(ctor,_) {
|
||||
fcx.ccx.sess.span_bug(ctor.span, "create_function: \
|
||||
expected a resource ctor here"); }
|
||||
// FIXME: output type may be wrong (#2194)
|
||||
(nm, ctor.node.dec.output, ctor.node.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_map::node_expr(expr) {
|
||||
alt expr.node {
|
||||
|
Loading…
x
Reference in New Issue
Block a user