diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index ced3d4971f7..e33d70913f2 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -577,9 +577,16 @@ private: public: size_of(const size_of &other, - const uint8_t *in_sp, - const type_param *in_params, - const rust_shape_tables *in_tables) + const uint8_t *in_sp = NULL, + const type_param *in_params = NULL, + const rust_shape_tables *in_tables = NULL) + : ctxt(other, in_sp, in_params, in_tables) {} + + template + size_of(const ctxt &other, + const uint8_t *in_sp = NULL, + const type_param *in_params = NULL, + const rust_shape_tables *in_tables = NULL) : ctxt(other, in_sp, in_params, in_tables) {} void walk_tag(bool align, tag_info &tinfo); @@ -612,9 +619,17 @@ public: template void walk_number(bool align) { sa.set(sizeof(T), ALIGNOF(T)); } + void compute_tag_size(tag_info &tinfo); + + template + static void compute_tag_size(const ctxt &other_cx, tag_info &tinfo) { + size_of cx(other_cx); + cx.compute_tag_size(tinfo); + } + template static size_align get(const ctxt &other_cx, unsigned back_up = 0) { - size_of cx(*other_cx, other_cx->sp - back_up); + size_of cx(other_cx, other_cx->sp - back_up); cx.walk(false); assert(cx.sa.alignment > 0); return cx.sa; @@ -622,15 +637,13 @@ public: }; void -size_of::walk_tag(bool align, tag_info &tinfo) { +size_of::compute_tag_size(tag_info &tinfo) { // If the precalculated size and alignment are good, use them. - if (tinfo.tag_sa.is_set()) { - sa = tinfo.tag_sa; + if (tinfo.tag_sa.is_set()) return; - } uint16_t n_largest_variants = get_u16_bump(tinfo.largest_variants_ptr); - sa.set(0, 0); + tinfo.tag_sa.set(0, 0); for (uint16_t i = 0; i < n_largest_variants; i++) { uint16_t variant_id = get_u16_bump(tinfo.largest_variants_ptr); uint16_t variant_offset = get_u16(tinfo.info_ptr + @@ -654,19 +667,25 @@ size_of::walk_tag(bool align, tag_info &tinfo) { variant_sa.add(sub.sa.size, sub.sa.alignment); } - if (sa.size < variant_sa.size) - sa = variant_sa; + if (tinfo.tag_sa.size < variant_sa.size) + tinfo.tag_sa = variant_sa; } if (tinfo.variant_count == 1) { - if (!sa.size) - sa.set(1, 1); + if (!tinfo.tag_sa.size) + tinfo.tag_sa.set(1, 1); } else { // Add in space for the tag. - sa.add(sizeof(uint32_t), ALIGNOF(uint32_t)); + tinfo.tag_sa.add(sizeof(uint32_t), ALIGNOF(uint32_t)); } } +void +size_of::walk_tag(bool align, tag_info &tinfo) { + compute_tag_size(*this, tinfo); + sa = tinfo.tag_sa; +} + void size_of::walk_struct(bool align, const uint8_t *end_sp) { size_align struct_sa(0, 1); @@ -696,32 +715,27 @@ size_of::walk_ivec(bool align, bool is_pod, size_align &elem_sa) { } -#if 0 - // An abstract class (again using the curiously recurring template pattern) // for methods that actually manipulate the data involved. #define DATA_SIMPLE(ty, call) \ - if (align) dp.align(sizeof(ty)); \ + if (align) dp.align_to(sizeof(ty)); \ static_cast(this)->call; \ dp += sizeof(ty); -template -class data : public ctxt { +template +class data : public ctxt< data > { private: - U dp; + typename T::data_ptr dp; public: - void walk_tag(bool align, uint16_t tag_id, const uint8_t *info_ptr, - uint16_t variant_count, const uint8_t *largest_variants_ptr, - size_align &tag_sa, uint16_t n_params, - const type_param *params); + void walk_tag(bool align, tag_info &tinfo); void walk_ivec(bool align, bool is_pod, size_align &elem_sa); void walk_struct(bool align, const uint8_t *end_sp) { - while (sp != end_sp) { + while (this->sp != end_sp) { // TODO: Allow subclasses to optimize for POD if they want to. - walk(align); + this->walk(align); align = true; } } @@ -736,14 +750,14 @@ public: void walk_task(bool align) { DATA_SIMPLE(void *, walk_task(align)); } void walk_fn(bool align) { - if (align) dp.align(sizeof(void *)); - static_cast(this)->walk_fn(args); + if (align) dp.align_to(sizeof(void *)); + static_cast(this)->walk_fn(align); dp += sizeof(void *) * 2; } void walk_obj(bool align) { - if (align) dp.align(sizeof(void *)); - static_cast(this)->walk_obj(args); + if (align) dp.align_to(sizeof(void *)); + static_cast(this)->walk_obj(align); dp += sizeof(void *) * 2; } @@ -757,17 +771,18 @@ public: } }; -template +template void -data::walk_ivec(bool align, bool is_pod, size_align &elem_sa) { +data::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. - if (align) dp.align(ALIGNOF(rust_ivec *)); - U end_dp = dp + sizeof(rust_ivec) - sizeof(uintptr_t) + elem_sa.size * 4; + if (align) dp.align_to(ALIGNOF(rust_ivec *)); + typename T::data_ptr end_dp = dp + sizeof(rust_ivec) - sizeof(uintptr_t) + + elem_sa.size * 4; // Call to the implementation. static_cast(this)->walk_ivec(align, is_pod, elem_sa); @@ -775,28 +790,35 @@ data::walk_ivec(bool align, bool is_pod, size_align &elem_sa) { dp = end_dp; } -template +template void -data::walk_tag(bool align, uint16_t tag_id, const uint8_t *info_ptr, - uint16_t variant_count, - const uint8_t *largest_variants_ptr, size_align &tag_sa, - uint16_t n_params, const type_param *params) { - uint32_t tag_variant; - U end_dp; - if (variant_count > 1) { - if (align) dp.align(ALIGNOF(uint32_t)); - process_tag_variant_ids( - U::data tag_variant = -} +data::walk_tag(bool align, tag_info &tinfo) { + size_of::compute_tag_size(tinfo); -#endif + if (tinfo.variant_count > 1 && align) + dp.align_to(ALIGNOF(uint32_t)); + + typename T::data_ptr end_dp = tinfo.tag_sa.size; + + typename T::template data tag_variant; + if (tinfo.variant_count > 1) + tag_variant = dp.template get_bump(); + else + tag_variant = 0; + + static_cast(this)->walk_tag(align, tinfo, tag_variant); +} // Copy constructors -class copy : public ctxt { +#if 0 + +class copy : public data { // TODO }; +#endif + } // end namespace shape