From 90e329da6b263cde1fc286e2c4aa6d062a6acf8a Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 21 Jan 2011 12:09:25 -0800 Subject: [PATCH] First cut at translating const items. Support the literal forms at least. Un-XFAIL const.rs. --- src/Makefile | 1 + src/comp/middle/trans.rs | 100 +++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4f27b434abf..385558b6062 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 57f5b002b65..49d8a7caeef 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, "")); - auto V_filename = p2i(C_str(cx.fcx.ccx, e.span.filename)); + auto V_expr_str = p2i(C_cstr(cx.fcx.ccx, "")); + 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,