diff --git a/src/Makefile b/src/Makefile index 43cb1a7f579..2c35d07f649 100644 --- a/src/Makefile +++ b/src/Makefile @@ -453,7 +453,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \ foreach-put-structured.rs \ foreach-simple-outer-slot.rs \ generic-iter-frame.rs \ - generic-tag-alt.rs \ generic-tag-values.rs \ iter-range.rs \ iter-ret.rs \ diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index f105247bb79..7dea9e0c0ec 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1730,6 +1730,25 @@ fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] { fail; // not reached } +// Returns the tag variant with the given ID. +fn tag_variant_with_id(@crate_ctxt cx, + &ast.def_id tag_id, + &ast.def_id variant_id) -> ast.variant { + auto variants = tag_variants(cx, tag_id); + + auto i = 0u; + while (i < _vec.len[ast.variant](variants)) { + auto variant = variants.(i); + if (common.def_eq(variant.id, variant_id)) { + ret variant; + } + i += 1u; + } + + log "tag_variant_with_id(): no variant exists with that ID"; + fail; +} + // Returns a new plain tag type of the given ID with no type parameters. Don't // use this function in new code; it's a hack to keep things working for now. fn mk_plain_tag(ast.def_id tid) -> @ty.t { @@ -2909,23 +2928,6 @@ fn trans_do_while(@block_ctxt cx, &ast.block body, // Pattern matching translation -// Returns a pointer to the union part of the LLVM representation of a tag -// type, cast to the appropriate type. -fn get_pat_union_ptr(@block_ctxt cx, vec[@ast.pat] subpats, ValueRef llval) - -> ValueRef { - auto llblobptr = cx.build.GEP(llval, vec(C_int(0), C_int(1))); - - // Generate the union type. - let vec[TypeRef] llsubpattys = vec(); - for (@ast.pat subpat in subpats) { - llsubpattys += vec(type_of(cx.fcx.ccx, pat_ty(subpat))); - } - - // Recursively check subpatterns. - auto llunionty = T_struct(llsubpattys); - ret cx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty)); -} - fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, @block_ctxt next_cx) -> result { alt (pat.node) { @@ -2943,7 +2945,11 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, } case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) { - auto lldiscrimptr = cx.build.GEP(llval, vec(C_int(0), C_int(0))); + auto lltagptr = cx.build.PointerCast(llval, + T_opaque_tag_ptr(cx.fcx.ccx.tn)); + + auto lldiscrimptr = cx.build.GEP(lltagptr, + vec(C_int(0), C_int(0))); auto lldiscrim = cx.build.Load(lldiscrimptr); auto vdef = option.get[ast.variant_def](vdef_opt); @@ -2968,13 +2974,15 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval, cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb); if (_vec.len[@ast.pat](subpats) > 0u) { - auto llunionptr = get_pat_union_ptr(matched_cx, subpats, - llval); + auto llblobptr = matched_cx.build.GEP(lltagptr, + vec(C_int(0), C_int(1))); auto i = 0; for (@ast.pat subpat in subpats) { - auto llsubvalptr = matched_cx.build.GEP(llunionptr, - vec(C_int(0), - C_int(i))); + auto rslt = GEP_tag(matched_cx, llblobptr, variants.(i), + i); + auto llsubvalptr = rslt.val; + matched_cx = rslt.bcx; + auto llsubval = load_scalar_or_boxed(matched_cx, llsubvalptr, pat_ty(subpat)); @@ -2998,25 +3006,35 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval) case (ast.pat_lit(_, _)) { ret res(cx, llval); } case (ast.pat_bind(?id, ?def_id, ?ann)) { auto ty = node_ann_type(cx.fcx.ccx, ann); - auto llty = type_of(cx.fcx.ccx, ty); - auto dst = cx.build.Alloca(llty); + auto rslt = alloc_ty(cx, ty); + auto dst = rslt.val; + auto bcx = rslt.bcx; + llvm.LLVMSetValueName(dst, _str.buf(id)); - cx.fcx.lllocals.insert(def_id, dst); - cx.cleanups += clean(bind drop_slot(_, dst, ty)); + bcx.fcx.lllocals.insert(def_id, dst); + bcx.cleanups += clean(bind drop_slot(_, dst, ty)); - ret copy_ty(cx, INIT, dst, llval, ty); + ret copy_ty(bcx, INIT, dst, llval, ty); } - case (ast.pat_tag(_, ?subpats, _, _)) { + case (ast.pat_tag(_, ?subpats, ?vdef_opt, _)) { if (_vec.len[@ast.pat](subpats) == 0u) { ret res(cx, llval); } - auto llunionptr = get_pat_union_ptr(cx, subpats, llval); + // Get the appropriate variant for this tag. + auto vdef = option.get[ast.variant_def](vdef_opt); + auto variant = tag_variant_with_id(cx.fcx.ccx, vdef._0, vdef._1); + + auto lltagptr = cx.build.PointerCast(llval, + T_opaque_tag_ptr(cx.fcx.ccx.tn)); + auto llblobptr = cx.build.GEP(lltagptr, vec(C_int(0), C_int(1))); auto this_cx = cx; auto i = 0; for (@ast.pat subpat in subpats) { - auto llsubvalptr = this_cx.build.GEP(llunionptr, - vec(C_int(0), C_int(i))); + auto rslt = GEP_tag(this_cx, llblobptr, variant, i); + this_cx = rslt.bcx; + auto llsubvalptr = rslt.val; + auto llsubval = load_scalar_or_boxed(this_cx, llsubvalptr, pat_ty(subpat)); auto subpat_res = trans_pat_binding(this_cx, subpat,