about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-03-03 15:52:54 -0800
committerPatrick Walton <pcwalton@mimiga.net>2011-03-03 15:53:36 -0800
commitf44fea8b6d77c24785fc351c5ca334df47b804b3 (patch)
treeab6222da4e24208c97a1dcf67760478c1b66cb88
parent5c7db0cde15adfda5b43112ee86d4bfe3bd9ee82 (diff)
rustc: Teach trans_tag_variant() about generic tags
-rw-r--r--src/comp/middle/trans.rs46
1 files changed, 35 insertions, 11 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 65f5b135e68..e85bcbbc68e 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -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;