rustc: Teach trans_tag_variant() about generic tags

This commit is contained in:
Patrick Walton 2011-03-03 15:52:54 -08:00
parent 5c7db0cde1
commit f44fea8b6d

View File

@ -397,6 +397,16 @@ fn T_opaque_closure_ptr(type_names tn) -> TypeRef {
ret t;
}
fn T_opaque_tag_ptr(type_names tn) -> TypeRef {
auto s = "*tag";
if (tn.name_has_type(s)) {
ret tn.get_type(s);
}
auto t = T_ptr(T_struct(vec(T_int(), T_i8())));
tn.associate(s, t);
ret t;
}
fn T_captured_tydescs(type_names tn, uint n) -> TypeRef {
ret T_struct(_vec.init_elt[TypeRef](T_ptr(T_tydesc(tn)), n));
}
@ -4576,27 +4586,41 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
auto arg_tys = arg_tys_of_fn(variant.ann);
copy_args_to_allocas(bcx, none[TypeRef], fn_args, arg_tys);
auto lldiscrimptr = bcx.build.GEP(fcx.llretptr,
// Now synthesize a tuple type for the arguments, so that GEP_tup_like()
// will know what the data part of the variant looks like.
let vec[@ty.t] true_arg_tys = vec();
for (ty.arg a in arg_tys) {
true_arg_tys += vec(a.ty);
}
auto tup_ty = ty.plain_ty(ty.ty_tup(true_arg_tys));
// Cast the tag to a type we can GEP into.
auto lltagptr = bcx.build.PointerCast(fcx.llretptr,
T_opaque_tag_ptr(fcx.ccx.tn));
auto lldiscrimptr = bcx.build.GEP(lltagptr,
vec(C_int(0), C_int(0)));
bcx.build.Store(C_int(index), lldiscrimptr);
auto llblobptr = bcx.build.GEP(fcx.llretptr,
auto llblobptr = bcx.build.GEP(lltagptr,
vec(C_int(0), C_int(1)));
// First, generate the union type.
let vec[TypeRef] llargtys = vec();
for (ty.arg arg in arg_tys) {
llargtys += vec(type_of(cx, arg.ty));
// Cast the blob pointer to the appropriate type, if we need to (i.e. if
// the blob pointer isn't dynamically sized).
let ValueRef llunionptr;
if (!ty.type_has_dynamic_size(tup_ty)) {
auto llty = type_of(cx, tup_ty);
llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llty));
} else {
llunionptr = llblobptr;
}
auto llunionty = T_struct(llargtys);
auto llunionptr = bcx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty));
i = 0u;
for (ast.variant_arg va in variant.args) {
auto llargval = bcx.build.Load(fcx.llargs.get(va.id));
auto lldestptr = bcx.build.GEP(llunionptr,
vec(C_int(0), C_int(i as int)));
auto rslt = GEP_tup_like(bcx, tup_ty, llunionptr, vec(0, i as int));
bcx = rslt.bcx;
auto lldestptr = rslt.val;
bcx.build.Store(llargval, lldestptr);
i += 1u;