mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
librustc: Implement C-like enum constants. r=tjc
This commit is contained in:
parent
f34833abfc
commit
5b5a0df7ee
@ -312,7 +312,7 @@ extern mod llvm {
|
||||
fn LLVMStructType(ElementTypes: *TypeRef, ElementCount: c_uint,
|
||||
Packed: Bool) -> TypeRef;
|
||||
fn LLVMCountStructElementTypes(StructTy: TypeRef) -> c_uint;
|
||||
fn LLVMGetStructElementTypes(StructTy: TypeRef, Dest: *TypeRef);
|
||||
fn LLVMGetStructElementTypes(StructTy: TypeRef, Dest: *mut TypeRef);
|
||||
fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool;
|
||||
|
||||
/* Operations on array, pointer, and vector types (sequence types) */
|
||||
@ -1123,10 +1123,9 @@ fn type_to_str_inner(names: type_names, outer0: ~[TypeRef], ty: TypeRef) ->
|
||||
Struct => {
|
||||
let mut s: ~str = ~"{";
|
||||
let n_elts = llvm::LLVMCountStructElementTypes(ty) as uint;
|
||||
let elts = vec::from_elem(n_elts, 0 as TypeRef);
|
||||
unsafe {
|
||||
llvm::LLVMGetStructElementTypes(ty, vec::raw::to_ptr(elts));
|
||||
}
|
||||
let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
|
||||
llvm::LLVMGetStructElementTypes(ty,
|
||||
ptr::to_mut_unsafe_ptr(&mut elts[0]));
|
||||
s += tys_str(names, outer, elts);
|
||||
s += ~"}";
|
||||
return s;
|
||||
@ -1179,6 +1178,18 @@ fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] unsafe {
|
||||
return args;
|
||||
}
|
||||
|
||||
fn struct_element_types(struct_ty: TypeRef) -> ~[TypeRef] {
|
||||
unsafe {
|
||||
let count = llvm::LLVMCountStructElementTypes(struct_ty);
|
||||
let mut buf: ~[TypeRef] =
|
||||
vec::from_elem(count as uint,
|
||||
cast::transmute::<uint,TypeRef>(0));
|
||||
llvm::LLVMGetStructElementTypes(struct_ty,
|
||||
ptr::to_mut_unsafe_ptr(&mut buf[0]));
|
||||
return move buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Memory-managed interface to target data. */
|
||||
|
||||
|
@ -94,7 +94,8 @@ fn check_expr(sess: Session, def_map: resolve::DefMap,
|
||||
}
|
||||
match def_map.find(e.id) {
|
||||
Some(def_const(def_id)) |
|
||||
Some(def_fn(def_id, _)) => {
|
||||
Some(def_fn(def_id, _)) |
|
||||
Some(def_variant(_, def_id)) => {
|
||||
if !ast_util::is_local(def_id) {
|
||||
sess.span_err(
|
||||
e.span, ~"paths in constants may only refer to \
|
||||
|
@ -581,8 +581,9 @@ fn val_str(tn: type_names, v: ValueRef) -> ~str {
|
||||
fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
|
||||
let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint;
|
||||
assert (n < elt_count);
|
||||
let elt_tys = vec::from_elem(elt_count, T_nil());
|
||||
llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
|
||||
let mut elt_tys = vec::from_elem(elt_count, T_nil());
|
||||
llvm::LLVMGetStructElementTypes(llstructty,
|
||||
ptr::to_mut_unsafe_ptr(&mut elt_tys[0]));
|
||||
return llvm::LLVMGetElementType(elt_tys[n]);
|
||||
}
|
||||
|
||||
@ -822,11 +823,12 @@ fn T_task(targ_cfg: @session::config) -> TypeRef {
|
||||
fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef unsafe {
|
||||
// Bit of a kludge: pick the fn typeref out of the tydesc..
|
||||
|
||||
let tydesc_elts: ~[TypeRef] =
|
||||
let mut tydesc_elts: ~[TypeRef] =
|
||||
vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
|
||||
T_nil());
|
||||
llvm::LLVMGetStructElementTypes(cx.tydesc_type,
|
||||
to_ptr::<TypeRef>(tydesc_elts));
|
||||
llvm::LLVMGetStructElementTypes(
|
||||
cx.tydesc_type,
|
||||
ptr::to_mut_unsafe_ptr(&mut tydesc_elts[0]));
|
||||
let t = llvm::LLVMGetElementType(tydesc_elts[field]);
|
||||
return t;
|
||||
}
|
||||
|
@ -369,15 +369,51 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
|
||||
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)) => {
|
||||
get_const_val(cx, def_id)
|
||||
}
|
||||
_ => cx.sess.span_bug(e.span, ~"expected a const or fn def")
|
||||
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)) => {
|
||||
get_const_val(cx, def_id)
|
||||
}
|
||||
Some(ast::def_variant(enum_did, variant_did)) => {
|
||||
// Note that we know this is a C-like (nullary) enum variant,
|
||||
// or we wouldn't have gotten here -- the constant checker
|
||||
// forbids paths that don't map to C-like enum variants.
|
||||
let ety = ty::expr_ty(cx.tcx, e);
|
||||
let llty = type_of::type_of(cx, ety);
|
||||
let llstructtys = lib::llvm::struct_element_types(llty);
|
||||
|
||||
// Can't use `discrims` from the crate context here because
|
||||
// those discriminants have an extra level of indirection,
|
||||
// and there's no LLVM constant load instruction.
|
||||
let mut lldiscrim_opt = None;
|
||||
for ty::enum_variants(cx.tcx, enum_did).each |variant_info| {
|
||||
if variant_info.id == variant_did {
|
||||
lldiscrim_opt = Some(C_int(cx,
|
||||
variant_info.disr_val));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let lldiscrim;
|
||||
match lldiscrim_opt {
|
||||
None => {
|
||||
cx.tcx.sess.span_bug(e.span,
|
||||
~"didn't find discriminant?!");
|
||||
}
|
||||
Some(found_lldiscrim) => {
|
||||
lldiscrim = found_lldiscrim;
|
||||
}
|
||||
}
|
||||
|
||||
C_named_struct(llty, ~[ lldiscrim, C_null(llstructtys[1]) ])
|
||||
}
|
||||
_ => {
|
||||
cx.sess.span_bug(e.span,
|
||||
~"expected a const, fn, or variant def")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::expr_paren(e) => { return const_expr(cx, e); }
|
||||
|
@ -75,10 +75,9 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||
|
||||
fn struct_tys(ty: TypeRef) -> ~[TypeRef] {
|
||||
let n = llvm::LLVMCountStructElementTypes(ty);
|
||||
let elts = vec::from_elem(n as uint, ptr::null());
|
||||
do vec::as_imm_buf(elts) |buf, _len| {
|
||||
llvm::LLVMGetStructElementTypes(ty, buf);
|
||||
}
|
||||
let mut elts = vec::from_elem(n as uint, ptr::null());
|
||||
llvm::LLVMGetStructElementTypes(ty,
|
||||
ptr::to_mut_unsafe_ptr(&mut elts[0]));
|
||||
return elts;
|
||||
}
|
||||
|
||||
|
15
src/test/run-pass/const-nullary-enum.rs
Normal file
15
src/test/run-pass/const-nullary-enum.rs
Normal file
@ -0,0 +1,15 @@
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
Boo,
|
||||
}
|
||||
|
||||
const X: Foo = Bar;
|
||||
|
||||
fn main() {
|
||||
match X {
|
||||
Bar => {}
|
||||
Baz | Boo => fail
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user