about summary refs log tree commit diff
path: root/src/rt/rust_shape.cpp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-08-08 19:16:33 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-08-08 19:16:33 -0700
commitf7749b16087182813afa715fa828bb674ce9ef72 (patch)
tree95f8d03de6a1ed1d07b1ebdc77a7677dcf289872 /src/rt/rust_shape.cpp
parent7d7f62613a49c03851fcde9fddb14ec6b474c50f (diff)
downloadrust-f7749b16087182813afa715fa828bb674ce9ef72.tar.gz
rust-f7749b16087182813afa715fa828bb674ce9ef72.zip
rt: Add code to walk over interior vectors, untested as of yet
Diffstat (limited to 'src/rt/rust_shape.cpp')
-rw-r--r--src/rt/rust_shape.cpp111
1 files changed, 84 insertions, 27 deletions
diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp
index 28de981b320..7f8373f74db 100644
--- a/src/rt/rust_shape.cpp
+++ b/src/rt/rust_shape.cpp
@@ -171,6 +171,10 @@ public:
         return make(fst - n, snd - n);
     }
 
+    inline bool operator<(const ptr_pair &other) const {
+        return fst < other.fst && snd < other.snd;
+    }
+
     static inline ptr_pair make(uint8_t *fst, uint8_t *snd) {
         ptr_pair self(fst, snd);
         return self;
@@ -817,6 +821,12 @@ size_of::walk_ivec(bool align, bool is_pod, size_align &elem_sa) {
 
 template<typename T,typename U>
 class data : public ctxt< data<T,U> > {
+protected:
+    void walk_variant(bool align, tag_info &tinfo, uint32_t variant);
+
+    static std::pair<uint8_t *,uint8_t *> get_ivec_data_range(uint8_t *dp);
+    static std::pair<ptr_pair,ptr_pair> get_ivec_data_range(ptr_pair &dp);
+
 public:
     U dp;
 
@@ -866,22 +876,62 @@ public:
         static_cast<T *>(this)->walk_var(align, param_index);
     }
 
-    // Called by derived classes only.
-    void walk_variant(bool align, tag_info &tinfo, uint32_t variant);
-
     template<typename W>
     void walk_number(bool align) { DATA_SIMPLE(W, walk_number<W>()); }
 };
 
 template<typename T,typename U>
 void
+data<T,U>::walk_variant(bool align, tag_info &tinfo, uint32_t variant_id) {
+    std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
+        this->get_variant_sp(tinfo, variant_id);
+    static_cast<T *>(this)->walk_variant(align, tinfo, variant_id,
+                                         variant_ptr_and_end);
+}
+
+template<typename T,typename U>
+std::pair<uint8_t *,uint8_t *>
+data<T,U>::get_ivec_data_range(uint8_t *dp) {
+    size_t fill = bump_dp<size_t>(dp);
+    bump_dp<size_t>(dp);    // Skip over alloc.
+    rust_ivec_payload payload = bump_dp<rust_ivec_payload>(dp);
+
+    uint8_t *start, *end;
+    if (!fill) {
+        if (!payload.ptr) {             // Zero length.
+            start = end = NULL;
+        } else {                        // On heap.
+            fill = payload.ptr->fill;
+            start = payload.ptr->data;
+            end = start + fill;
+        }
+    } else {                            // On stack.
+        start = payload.data;
+        end = start + fill;
+    }
+
+    return std::make_pair(start, end);
+}
+
+template<typename T,typename U>
+std::pair<ptr_pair,ptr_pair>
+data<T,U>::get_ivec_data_range(ptr_pair &dp) {
+    std::pair<uint8_t *,uint8_t *> fst = get_ivec_data_range(dp.fst);
+    std::pair<uint8_t *,uint8_t *> snd = get_ivec_data_range(dp.snd);
+    ptr_pair start(fst.first, snd.first);
+    ptr_pair end(fst.second, snd.second);
+    return std::make_pair(start, end);
+}
+
+template<typename T,typename U>
+void
 data<T,U>::walk_ivec(bool align, bool is_pod, size_align &elem_sa) {
     if (!elem_sa.is_set())
         elem_sa = size_of::get(*this);
     else if (elem_sa.alignment == 8)
         elem_sa.alignment = 4;  // FIXME: This is an awful hack.
 
-    // Get a pointer to the interior vector, and skip over it.
+    // Get a pointer to the interior vector, and determine its size.
     if (align) dp = align_to(dp, ALIGNOF(rust_ivec *));
     U end_dp = dp + sizeof(rust_ivec) - sizeof(uintptr_t) + elem_sa.size * 4;
 
@@ -910,15 +960,6 @@ data<T,U>::walk_tag(bool align, tag_info &tinfo) {
     static_cast<T *>(this)->walk_tag(align, tinfo, tag_variant);
 }
 
-template<typename T,typename U>
-void
-data<T,U>::walk_variant(bool align, tag_info &tinfo, uint32_t variant_id) {
-    std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
-        this->get_variant_sp(tinfo, variant_id);
-    static_cast<T *>(this)->walk_variant(align, tinfo, variant_id,
-                                         variant_ptr_and_end);
-}
-
 
 // Copy constructors
 
@@ -968,10 +1009,11 @@ public:
                          in_dp),
       result(0) {}
 
-    void walk_box(bool align);
-    void walk_struct(bool align, const uint8_t *end_sp);
+    void walk_ivec(bool align, bool is_pod, size_align &elem_sa);
     void walk_tag(bool align, tag_info &tinfo,
                   const data_pair<uint32_t> &tag_variants);
+    void walk_box(bool align);
+    void walk_struct(bool align, const uint8_t *end_sp);
     void walk_res(bool align, const rust_fn *dtor, uint16_t n_ty_params,
                   const uint8_t *ty_params_sp);
     void walk_variant(bool align, tag_info &tinfo, uint32_t variant_id,
@@ -983,18 +1025,14 @@ public:
 };
 
 void
-cmp::walk_box(bool align) {
-    data_pair<uint8_t *> subdp = bump_dp<uint8_t *>(dp);
-    cmp subcx(*this, ptr_pair::make(subdp));
-    subcx.dp += sizeof(uint32_t);   // Skip over the reference count.
-    subcx.walk(true);
-    result = subcx.result;
-}
+cmp::walk_ivec(bool align, bool is_pod, size_align &elem_sa) {
+    std::pair<ptr_pair,ptr_pair> data_range = get_ivec_data_range(dp);
 
-void
-cmp::walk_struct(bool align, const uint8_t *end_sp) {
-    while (!result && this->sp != end_sp) {
-        this->walk(align);
+    cmp sub(*this, data_range.first);
+    ptr_pair data_end = data_range.second;
+    while (!result && sub.dp < data_end) {
+        sub.walk(align);
+        result = sub.result;
         align = true;
     }
 }
@@ -1009,6 +1047,24 @@ cmp::walk_tag(bool align, tag_info &tinfo,
 }
 
 void
+cmp::walk_box(bool align) {
+    data_pair<uint8_t *> subdp = bump_dp<uint8_t *>(dp);
+
+    cmp sub(*this, ptr_pair::make(subdp));
+    sub.dp += sizeof(uint32_t);     // Skip over the reference count.
+    sub.walk(true);
+    result = sub.result;
+}
+
+void
+cmp::walk_struct(bool align, const uint8_t *end_sp) {
+    while (!result && this->sp != end_sp) {
+        this->walk(align);
+        align = true;
+    }
+}
+
+void
 cmp::walk_res(bool align, const rust_fn *dtor, uint16_t n_ty_params,
               const uint8_t *ty_params_sp) {
     abort();    // TODO
@@ -1021,8 +1077,9 @@ cmp::walk_variant(bool align, tag_info &tinfo, uint32_t variant_id,
     cmp sub(*this, variant_ptr_and_end.first);
 
     const uint8_t *variant_end = variant_ptr_and_end.second;
-    while (!sub.result && sub.sp < variant_end) {
+    while (!result && sub.sp < variant_end) {
         sub.walk(align);
+        result = sub.result;
         align = true;
     }
 }