From edfc79cc4798798ecaf4e7fead54dd2e1c3e703e Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 3 Aug 2012 21:44:42 -0700 Subject: [PATCH] Translate const vecs, most of const slices. More for #2317. --- src/rustc/middle/check_const.rs | 8 ++-- src/rustc/middle/trans/consts.rs | 49 +++++++++++++++++++--- src/test/run-pass/const-region-ptrs.rs | 4 +- src/test/run-pass/const-vecs-and-slices.rs | 7 ++++ 4 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 src/test/run-pass/const-vecs-and-slices.rs diff --git a/src/rustc/middle/check_const.rs b/src/rustc/middle/check_const.rs index dbf60edca8e94..3d485338ffb99 100644 --- a/src/rustc/middle/check_const.rs +++ b/src/rustc/middle/check_const.rs @@ -66,10 +66,7 @@ fn check_expr(sess: session, def_map: resolve3::DefMap, ~"disallowed operator in constant expression"); return; } - expr_lit(@{node: lit_str(_), _}) { - sess.span_err(e.span, - ~"string constants are not supported"); - } + expr_lit(@{node: lit_str(_), _}) { } expr_binary(_, _, _) | expr_unary(_, _) { if method_map.contains_key(e.id) { sess.span_err(e.span, ~"user-defined operators are not \ @@ -101,6 +98,9 @@ fn check_expr(sess: session, def_map: resolve3::DefMap, } } } + expr_vstore(_, vstore_slice(_)) | + expr_vstore(_, vstore_fixed(_)) | + expr_vec(_, m_imm) | expr_addr_of(m_imm, _) | expr_tup(*) | expr_rec(*) { } diff --git a/src/rustc/middle/trans/consts.rs b/src/rustc/middle/trans/consts.rs index 8a8e284b5c040..03c0b303c0937 100644 --- a/src/rustc/middle/trans/consts.rs +++ b/src/rustc/middle/trans/consts.rs @@ -25,21 +25,29 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit) ast::lit_float(fs, t) { C_floating(*fs, T_float_ty(cx, t)) } ast::lit_bool(b) { C_bool(b) } ast::lit_nil { C_nil() } - ast::lit_str(s) { - cx.sess.span_unimpl(lit.span, ~"unique string in this context"); - } + ast::lit_str(s) { C_estr_slice(cx, *s) } } } // 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_vec_and_sz(cx: @crate_ctxt, e: @ast::expr, es: &[@ast::expr]) + -> (ValueRef, ValueRef) { + let vec_ty = ty::expr_ty(cx.tcx, e); + let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty); + let llunitty = type_of::type_of(cx, unit_ty); + let v = C_array(llunitty, es.map(|e| const_expr(cx, e))); + let unit_sz = shape::llsize_of(cx, llunitty); + let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz); + return (v, sz); +} + fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { let _icx = cx.insn_ctxt(~"const_expr"); alt e.node { ast::expr_lit(lit) { consts::const_lit(cx, e, *lit) } - // If we have a vstore, just keep going; it has to be a string - ast::expr_vstore(e, _) { const_expr(cx, e) } ast::expr_binary(b, e1, e2) { let te1 = const_expr(cx, e1); let te2 = const_expr(cx, e2); @@ -147,6 +155,37 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { ast::expr_rec(fs, none) { C_struct(fs.map(|f| const_expr(cx, f.node.expr))) } + ast::expr_vec(es, m_imm) { + let (v, _) = const_vec_and_sz(cx, e, es); + v + } + ast::expr_vstore(e, ast::vstore_fixed(_)) { + const_expr(cx, e) + } + ast::expr_vstore(sub, ast::vstore_slice(_)) { + alt sub.node { + ast::expr_lit(lit) { + alt lit.node { + ast::lit_str(*) => { const_expr(cx, sub) } + _ => { cx.sess.span_bug(e.span, + ~"bad const-slice lit") } + } + } + ast::expr_vec(es, m_imm) => { + let (cv, sz) = const_vec_and_sz(cx, e, es); + let subty = ty::expr_ty(cx.tcx, sub), + llty = type_of::type_of(cx, subty); + let gv = do str::as_c_str("const") |name| { + llvm::LLVMAddGlobal(cx.llmod, llty, name) + }; + llvm::LLVMSetInitializer(gv, cv); + llvm::LLVMSetGlobalConstant(gv, True); + C_struct(~[gv, sz]) + } + _ => cx.sess.span_bug(e.span, + ~"bad const-slice expr") + } + } ast::expr_path(path) { alt cx.tcx.def_map.find(e.id) { some(ast::def_const(def_id)) { diff --git a/src/test/run-pass/const-region-ptrs.rs b/src/test/run-pass/const-region-ptrs.rs index 2ce212c158dd2..4fb90af66a2a0 100644 --- a/src/test/run-pass/const-region-ptrs.rs +++ b/src/test/run-pass/const-region-ptrs.rs @@ -4,6 +4,8 @@ const x: &int = &10; const y: &{a: int, b: &int} = &{a: 15, b: x}; fn main() { - io::println(fmt!("x = %?", x)); + io::println(fmt!("x = %?", *x)); io::println(fmt!("y = {a: %?, b: %?}", y.a, *(y.b))); + assert *x == 10; + assert *(y.b) == 10; } diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs new file mode 100644 index 0000000000000..4e5b7e81e9aee --- /dev/null +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -0,0 +1,7 @@ +const x : [int]/4 = [1,2,3,4]; + +fn main() { + io::println(fmt!("%?", x[1])); + assert x[1] == 2; + assert x[3] == 4; +} \ No newline at end of file