diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2011-08-08 19:16:33 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2011-08-08 19:16:33 -0700 |
| commit | f7749b16087182813afa715fa828bb674ce9ef72 (patch) | |
| tree | 95f8d03de6a1ed1d07b1ebdc77a7677dcf289872 /src/rt/rust_shape.cpp | |
| parent | 7d7f62613a49c03851fcde9fddb14ec6b474c50f (diff) | |
| download | rust-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.cpp | 111 |
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; } } |
