Skip to content

Commit

Permalink
rustc: reuse const vals, translate fn paths as consts. Close rust-lan…
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Nov 7, 2012
1 parent b0ed151 commit 92e3a8c
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 43 deletions.
18 changes: 3 additions & 15 deletions src/libcore/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,16 @@ struct Guard<T, U:Copy> {
mod test {

fn sadness_key(_x: @Handler<int,int>) { }
const sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

fn trouble(i: int) {
// Condition should work as a const, just limitations in consts.
let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };
debug!("trouble: raising conition");
let j = sadness_condition.raise(&i);
debug!("trouble: handler recovered with %d", j);
}

fn nested_trap_test_inner() {
let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

let mut inner_trapped = false;

Expand All @@ -126,9 +124,6 @@ mod test {
#[test]
fn nested_trap_test_outer() {

let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

let mut outer_trapped = false;

do sadness_condition.trap(|_j| {
Expand All @@ -144,8 +139,6 @@ mod test {
}

fn nested_reraise_trap_test_inner() {
let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

let mut inner_trapped = false;

Expand All @@ -166,9 +159,6 @@ mod test {
#[test]
fn nested_reraise_trap_test_outer() {

let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

let mut outer_trapped = false;

do sadness_condition.trap(|_j| {
Expand All @@ -184,8 +174,6 @@ mod test {

#[test]
fn test_default() {
let sadness_condition : Condition<int,int> =
Condition { key: sadness_key };

let mut trapped = false;

Expand Down
19 changes: 15 additions & 4 deletions src/rustc/middle/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,30 @@ fn check_expr(sess: Session, def_map: resolve::DefMap,
~"` in a constant expression");
}
}
expr_path(_) => {
expr_path(pth) => {
// NB: In the future you might wish to relax this slightly
// to handle on-demand instantiation of functions via
// foo::<bar> in a const. Currently that is only done on
// a path in trans::callee that only works in block contexts.
if pth.types.len() != 0 {
sess.span_err(
e.span, ~"paths in constants may only refer to \
items without type parameters");
}
match def_map.find(e.id) {
Some(def_const(def_id)) => {
Some(def_const(def_id)) |
Some(def_fn(def_id, _)) => {
if !ast_util::is_local(def_id) {
sess.span_err(
e.span, ~"paths in constants may only refer to \
crate-local constants");
crate-local constants or functions");
}
}
_ => {
sess.span_err(
e.span,
~"paths in constants may only refer to constants");
~"paths in constants may only refer to \
constants or functions");
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,7 @@ fn trans_crate(sess: session::Session,
vtables: map::HashMap(),
const_cstr_cache: HashMap(),
const_globals: HashMap(),
const_values: HashMap(),
module_data: HashMap(),
lltypes: ty::new_ty_hash(),
names: new_namegen(sess.parse_sess.interner),
Expand Down
15 changes: 12 additions & 3 deletions src/rustc/middle/trans/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,19 @@ type crate_ctxt = {
vtables: HashMap<mono_id, ValueRef>,
// Cache of constant strings,
const_cstr_cache: HashMap<~str, ValueRef>,
// Reverse-direction for const ptrs cast from globals,
// since the ptr -> init association is lost any
// time a GlobalValue is cast.

// Reverse-direction for const ptrs cast from globals.
// Key is an int, cast from a ValueRef holding a *T,
// Val is a ValueRef holding a *[T].
//
// Needed because LLVM loses pointer->pointee association
// when we ptrcast, and we have to ptrcast during translation
// of a [T] const because we form a slice, a [*T,int] pair, not
// a pointer to an LLVM array type.
const_globals: HashMap<int, ValueRef>,

// Cache of emitted const values
const_values: HashMap<ast::node_id, ValueRef>,
module_data: HashMap<~str, ValueRef>,
lltypes: HashMap<ty::t, TypeRef>,
names: namegen,
Expand Down
41 changes: 20 additions & 21 deletions src/rustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit)
}
}

// FIXME (#2530): this should do some structural hash-consing to avoid
// duplicate constants. I think. Maybe LLVM has a magical mode that does so
// later on?

fn const_ptrcast(cx: @crate_ctxt, a: ValueRef, t: TypeRef) -> ValueRef {
let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
assert cx.const_globals.insert(b as int, a);
Expand Down Expand Up @@ -341,24 +337,29 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
~"bad const-slice expr")
}
}
ast::expr_path(_) => {
ast::expr_path(pth) => {
assert pth.types.len() == 0;
match cx.tcx.def_map.find(e.id) {
Some(ast::def_fn(def_id, _)) => {
assert ast_util::is_local(def_id);
let f = base::get_item_val(cx, def_id.node);
C_struct(~[f, C_null(T_opaque_box_ptr(cx))])
}
Some(ast::def_const(def_id)) => {
// Don't know how to handle external consts
assert ast_util::is_local(def_id);
match cx.tcx.items.get(def_id.node) {
ast_map::node_item(@{
node: ast::item_const(_, subexpr), _
}, _) => {
// FIXME (#2530): Instead of recursing here to regenerate
// the values for other constants, we should just look up
// the already-defined value.
const_expr(cx, subexpr)
}
_ => cx.sess.span_bug(e.span, ~"expected item")
if ! cx.const_values.contains_key(def_id.node) {
match cx.tcx.items.get(def_id.node) {
ast_map::node_item(@{
node: ast::item_const(_, subexpr), _
}, _) => {
trans_const(cx, subexpr, def_id.node);
}
_ => cx.sess.span_bug(e.span, ~"expected item")
}
}
cx.const_values.get(def_id.node)
}
_ => cx.sess.span_bug(e.span, ~"expected to find a const def")
_ => cx.sess.span_bug(e.span, ~"expected a const or fn def")
}
}
ast::expr_paren(e) => { return const_expr(cx, e); }
Expand All @@ -369,11 +370,9 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {

fn trans_const(ccx: @crate_ctxt, e: @ast::expr, id: ast::node_id) {
let _icx = ccx.insn_ctxt("trans_const");
let v = const_expr(ccx, e);

// The scalars come back as 1st class LLVM vals
// which we have to stick into global constants.
let g = base::get_item_val(ccx, id);
let v = const_expr(ccx, e);
ccx.const_values.insert(id, v);
llvm::LLVMSetInitializer(g, v);
llvm::LLVMSetGlobalConstant(g, True);
}
11 changes: 11 additions & 0 deletions src/test/run-pass/const-fn-val.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn foo() -> int {
return 0xca7f000d;
}

struct Bar { f: &fn() -> int }

const b : Bar = Bar { f: foo };

fn main() {
assert (b.f)() == 0xca7f000d;
}

0 comments on commit 92e3a8c

Please sign in to comment.