aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2011-01-21 12:09:25 -0800
committerGraydon Hoare <[email protected]>2011-01-21 12:09:25 -0800
commit90e329da6b263cde1fc286e2c4aa6d062a6acf8a (patch)
tree55b7a7b571be8752612e8eaaac69d07e34d03bef /src
parentMerge remote branch 'espindola/params' (diff)
downloadrust-90e329da6b263cde1fc286e2c4aa6d062a6acf8a.tar.xz
rust-90e329da6b263cde1fc286e2c4aa6d062a6acf8a.zip
First cut at translating const items. Support the literal forms at least. Un-XFAIL const.rs.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile1
-rw-r--r--src/comp/middle/trans.rs100
2 files changed, 75 insertions, 26 deletions
diff --git a/src/Makefile b/src/Makefile
index 4f27b434..385558b6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -432,6 +432,7 @@ TEST_XFAILS_RUSTC := $(filter-out \
cast.rs \
char.rs \
complex.rs \
+ const.rs \
dead-code-one-arm-if.rs \
deep.rs \
deref.rs \
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 57f5b002..49d8a7ca 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -70,6 +70,7 @@ state type crate_ctxt = rec(session.session sess,
hashmap[ast.def_id, @ast.item] items,
hashmap[ast.def_id, @tag_info] tags,
hashmap[ast.def_id, ValueRef] fn_pairs,
+ hashmap[ast.def_id, ValueRef] consts,
hashmap[ast.def_id,()] obj_methods,
hashmap[@ty.t, ValueRef] tydescs,
vec[ast.obj_field] obj_fields,
@@ -527,7 +528,9 @@ fn C_int(int i) -> ValueRef {
ret C_integral(i, T_int());
}
-fn C_str(@crate_ctxt cx, str s) -> ValueRef {
+// This is a 'c-like' raw string, which differs from
+// our boxed-and-length-annotated strings.
+fn C_cstr(@crate_ctxt cx, str s) -> ValueRef {
auto sc = llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(sc),
_str.buf(cx.names.next("str")));
@@ -538,6 +541,23 @@ fn C_str(@crate_ctxt cx, str s) -> ValueRef {
ret g;
}
+// A rust boxed-and-length-annotated string.
+fn C_str(@crate_ctxt cx, str s) -> ValueRef {
+ auto len = _str.byte_len(s);
+ auto box = C_struct(vec(C_int(abi.const_refcount as int),
+ C_int(len + 1u as int), // 'alloc'
+ C_int(len + 1u as int), // 'fill'
+ llvm.LLVMConstString(_str.buf(s),
+ len, False)));
+ auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(box),
+ _str.buf(cx.names.next("str")));
+ llvm.LLVMSetInitializer(g, box);
+ llvm.LLVMSetGlobalConstant(g, True);
+ llvm.LLVMSetLinkage(g, lib.llvm.LLVMPrivateLinkage
+ as llvm.Linkage);
+ ret llvm.LLVMConstPointerCast(g, T_ptr(T_str()));
+}
+
fn C_zero_byte_arr(uint size) -> ValueRef {
auto i = 0u;
let vec[ValueRef] elts = vec();
@@ -1504,13 +1524,13 @@ fn copy_ty(@block_ctxt cx,
fail;
}
-fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
+fn trans_lit(@crate_ctxt cx, &ast.lit lit, &ast.ann ann) -> ValueRef {
alt (lit.node) {
case (ast.lit_int(?i)) {
- ret res(cx, C_int(i));
+ ret C_int(i);
}
case (ast.lit_uint(?u)) {
- ret res(cx, C_int(u as int));
+ ret C_int(u as int);
}
case (ast.lit_mach_int(?tm, ?i)) {
// FIXME: the entire handling of mach types falls apart
@@ -1527,32 +1547,20 @@ fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
case (common.ty_i16) { t = T_i16(); }
case (common.ty_i32) { t = T_i32(); }
case (common.ty_i64) { t = T_i64(); }
- case (_) {
- cx.fcx.ccx.sess.bug("bad mach int literal type");
- }
}
- ret res(cx, C_integral(i, t));
+ ret C_integral(i, t);
}
case (ast.lit_char(?c)) {
- ret res(cx, C_integral(c as int, T_char()));
+ ret C_integral(c as int, T_char());
}
case (ast.lit_bool(?b)) {
- ret res(cx, C_bool(b));
+ ret C_bool(b);
}
case (ast.lit_nil) {
- ret res(cx, C_nil());
+ ret C_nil();
}
case (ast.lit_str(?s)) {
- auto len = (_str.byte_len(s) as int) + 1;
- auto sub = trans_upcall(cx, "upcall_new_str",
- vec(p2i(C_str(cx.fcx.ccx, s)),
- C_int(len)));
- auto val = sub.bcx.build.IntToPtr(sub.val,
- T_ptr(T_str()));
- auto t = node_ann_type(cx.fcx.ccx, ann);
- find_scope_cx(cx).cleanups +=
- clean(bind drop_ty(_, val, t));
- ret res(sub.bcx, val);
+ ret C_str(cx, s);
}
}
}
@@ -2087,6 +2095,10 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
ret lval_val(cx, cx.fcx.ccx.item_ids.get(vid));
}
}
+ case (ast.def_const(?did)) {
+ check (cx.fcx.ccx.consts.contains_key(did));
+ ret lval_mem(cx, cx.fcx.ccx.consts.get(did));
+ }
case (_) {
cx.fcx.ccx.sess.unimpl("def variant in trans");
}
@@ -2155,8 +2167,8 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
ix.bcx.build.CondBr(bounds_check, next_cx.llbb, fail_cx.llbb);
// fail: bad bounds check.
- auto V_expr_str = p2i(C_str(cx.fcx.ccx, "out-of-bounds access"));
- auto V_filename = p2i(C_str(cx.fcx.ccx, sp.filename));
+ auto V_expr_str = p2i(C_cstr(cx.fcx.ccx, "out-of-bounds access"));
+ auto V_filename = p2i(C_cstr(cx.fcx.ccx, sp.filename));
auto V_line = sp.lo.line as int;
auto args = vec(V_expr_str, V_filename, C_int(V_line));
auto fail_res = trans_upcall(fail_cx, "upcall_fail", args);
@@ -2667,7 +2679,7 @@ fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
alt (e.node) {
case (ast.expr_lit(?lit, ?ann)) {
- ret trans_lit(cx, *lit, ann);
+ ret res(cx, trans_lit(cx.fcx.ccx, *lit, ann));
}
case (ast.expr_unary(?op, ?x, ?ann)) {
@@ -2806,8 +2818,8 @@ fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
auto cond_res = trans_expr(cx, e);
// FIXME: need pretty-printer.
- auto V_expr_str = p2i(C_str(cx.fcx.ccx, "<expr>"));
- auto V_filename = p2i(C_str(cx.fcx.ccx, e.span.filename));
+ auto V_expr_str = p2i(C_cstr(cx.fcx.ccx, "<expr>"));
+ auto V_filename = p2i(C_cstr(cx.fcx.ccx, e.span.filename));
auto V_line = e.span.lo.line as int;
auto args = vec(V_expr_str, V_filename, C_int(V_line));
@@ -3495,6 +3507,37 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
bcx.build.Ret(lltagval);
}
+// FIXME: 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 trans_const_expr(@crate_ctxt cx, @ast.expr e) -> ValueRef {
+ alt (e.node) {
+ case (ast.expr_lit(?lit, ?ann)) {
+ ret trans_lit(cx, *lit, ann);
+ }
+ }
+}
+
+fn trans_const(@crate_ctxt cx, @ast.expr e,
+ &ast.def_id cid, &ast.ann ann) {
+ auto t = node_ann_type(cx, ann);
+ auto v = trans_const_expr(cx, e);
+ if (ty.type_is_scalar(t)) {
+ // The scalars come back as 1st class LLVM vals
+ // which we have to stick into global constants.
+ auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(v),
+ _str.buf(cx.names.next(cx.path)));
+ llvm.LLVMSetInitializer(g, v);
+ llvm.LLVMSetGlobalConstant(g, True);
+ llvm.LLVMSetLinkage(g, lib.llvm.LLVMPrivateLinkage
+ as llvm.Linkage);
+ cx.consts.insert(cid, g);
+ } else {
+ cx.consts.insert(cid, v);
+ }
+}
+
fn trans_item(@crate_ctxt cx, &ast.item item) {
alt (item.node) {
case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
@@ -3518,6 +3561,10 @@ fn trans_item(@crate_ctxt cx, &ast.item item) {
i += 1;
}
}
+ case (ast.item_const(?name, _, ?expr, ?cid, ?ann)) {
+ auto sub_cx = @rec(path=cx.path + "." + name with *cx);
+ trans_const(sub_cx, expr, cid, ann);
+ }
case (_) { /* fall through */ }
}
}
@@ -4055,6 +4102,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
items = new_def_hash[@ast.item](),
tags = new_def_hash[@tag_info](),
fn_pairs = new_def_hash[ValueRef](),
+ consts = new_def_hash[ValueRef](),
obj_methods = new_def_hash[()](),
tydescs = tydescs,
obj_fields = obj_fields,