1 // Functions that interpret the shape of a type to perform various low-level
2 // actions, such as copying, freeing, comparing, and so on.
7 // Tell ISAAC to let go of max() and min() defines.
12 #include "rust_internal.h"
14 // ISAAC pollutes our namespace.
17 #define ARENA_SIZE 256
19 //#define DPRINT(fmt,...) fprintf(stderr, fmt, ##__VA_ARGS__)
20 //#define DPRINTCX(cx) shape::print::print_cx(cx)
22 #define DPRINT(fmt,...)
28 typedef unsigned long tag_variant_t;
29 typedef unsigned long tag_align_t;
30 typedef unsigned long ref_cnt_t;
34 const uint8_t SHAPE_U8 = 0u;
35 const uint8_t SHAPE_U16 = 1u;
36 const uint8_t SHAPE_U32 = 2u;
37 const uint8_t SHAPE_U64 = 3u;
38 const uint8_t SHAPE_I8 = 4u;
39 const uint8_t SHAPE_I16 = 5u;
40 const uint8_t SHAPE_I32 = 6u;
41 const uint8_t SHAPE_I64 = 7u;
42 const uint8_t SHAPE_F32 = 8u;
43 const uint8_t SHAPE_F64 = 9u;
44 const uint8_t SHAPE_VEC = 11u;
45 const uint8_t SHAPE_TAG = 12u;
46 const uint8_t SHAPE_BOX = 13u;
47 const uint8_t SHAPE_STRUCT = 17u;
48 const uint8_t SHAPE_FN = 18u;
49 const uint8_t SHAPE_OBJ = 19u;
50 const uint8_t SHAPE_RES = 20u;
51 const uint8_t SHAPE_VAR = 21u;
52 const uint8_t SHAPE_UNIQ = 22u;
55 const uint8_t SHAPE_PTR = SHAPE_U64;
57 const uint8_t SHAPE_PTR = SHAPE_U32;
61 // Forward declarations
69 // Arenas; these functions must execute very quickly, so we use an arena
70 // instead of malloc or new.
74 uint8_t data[ARENA_SIZE];
77 arena() : ptr(data) {}
80 inline T *alloc(size_t count = 1) {
82 size_t sz = count * sizeof(T);
85 if (ptr > &data[ARENA_SIZE]) {
86 fprintf(stderr, "Arena space exhausted, sorry\n");
94 // Alignment inquiries
96 // We can't directly use __alignof__ everywhere because that returns the
97 // preferred alignment of the type, which is different from the ABI-mandated
98 // alignment of the type in some cases (e.g. doubles on x86). The latter is
99 // what actually gets used for struct elements.
107 return __alignof__(T);
124 size_align(size_t in_size = 0, size_t in_align = 1) :
125 size(in_size), alignment(in_align) {}
127 bool is_set() const { return alignment != 0; }
129 inline void set(size_t in_size, size_t in_align) {
131 alignment = in_align;
134 inline void add(const size_align &other) {
135 add(other.size, other.alignment);
138 inline void add(size_t extra_size, size_t extra_align) {
140 alignment = std::max(alignment, extra_align);
143 static inline size_align make(size_t in_size) {
145 sa.size = sa.alignment = in_size;
149 static inline size_align make(size_t in_size, size_t in_align) {
152 sa.alignment = in_align;
158 uint16_t tag_id; // The tag ID.
159 const uint8_t *info_ptr; // Pointer to the info table.
160 uint16_t variant_count; // Number of variants in the tag.
161 const uint8_t *largest_variants_ptr; // Ptr to largest variants table.
162 size_align tag_sa; // Size and align of this tag.
163 uint16_t n_params; // Number of type parameters.
164 const type_param *params; // Array of type parameters.
171 get_u16(const uint8_t *addr) {
172 return *reinterpret_cast<const uint16_t *>(addr);
176 get_u16_bump(const uint8_t *&addr) {
177 uint16_t result = get_u16(addr);
178 addr += sizeof(uint16_t);
184 fmt_number(std::ostream &out, T n) {
188 // Override the character interpretation for these two.
191 fmt_number<uint8_t>(std::ostream &out, uint8_t n) {
196 fmt_number<int8_t>(std::ostream &out, int8_t n) {
203 // The base context, an abstract class. We use the curiously recurring
204 // template pattern here to avoid virtual dispatch.
208 const uint8_t *sp; // shape pointer
209 const type_param *params; // shapes of type parameters
210 const rust_shape_tables *tables;
214 ctxt(rust_task *in_task,
216 const uint8_t *in_sp,
217 const type_param *in_params,
218 const rust_shape_tables *in_tables)
226 ctxt(const ctxt<U> &other,
227 const uint8_t *in_sp = NULL,
228 const type_param *in_params = NULL,
229 const rust_shape_tables *in_tables = NULL)
230 : sp(in_sp ? in_sp : other.sp),
231 params(in_params ? in_params : other.params),
232 tables(in_tables ? in_tables : other.tables),
234 align(other.align) {}
239 std::pair<const uint8_t *,const uint8_t *>
240 get_variant_sp(tag_info &info, tag_variant_t variant_id);
243 inline uint8_t peek() { return *sp; }
245 inline size_align get_size_align(const uint8_t *&addr);
261 void (*code)(uint8_t *rv, rust_task *task, void *env, ...);
265 struct rust_closure {
269 uint32_t bindings[0];
271 uint8_t *get_bindings() const { return (uint8_t *)bindings; }
274 struct rust_obj_box {
277 uint8_t *get_bindings() const { return (uint8_t *)this; }
281 CDECL void (*dtor)(void *rv, rust_task *task, rust_obj obj);
294 static type_param *make(const type_desc **tydescs, unsigned n_tydescs,
298 const uint8_t *shape;
299 const rust_shape_tables *tables;
300 const type_param *params; // subparameters
302 // Constructs type parameters from a function shape.
303 static type_param *from_fn_shape(const uint8_t *sp, ptr dp, arena &arena);
304 // Creates type parameters from an object shape description.
305 static type_param *from_obj_shape(const uint8_t *sp, ptr dp,
309 inline void set(ctxt<T> *cx) {
315 // Creates type parameters from a type descriptor.
316 static inline type_param *from_tydesc(const type_desc *tydesc,
318 // In order to find the type parameters of objects and functions, we
319 // have to actually have the data pointer, since we don't statically
320 // know from the type of an object or function which type parameters
322 assert(!tydesc->n_obj_params && "Type-parametric objects and "
323 "functions must go through from_tydesc_and_data() instead!");
325 return make(tydesc->first_param, tydesc->n_params, arena);
328 static type_param *from_tydesc_and_data(const type_desc *tydesc,
329 uint8_t *dp, arena &arena) {
330 if (tydesc->n_obj_params) {
331 uintptr_t n_obj_params = tydesc->n_obj_params;
332 const type_desc **first_param;
333 if (n_obj_params & 0x80000000) {
335 DPRINT("n_obj_params FN %lu, tydesc %p, starting at %p\n",
336 (unsigned long)n_obj_params, tydesc,
337 dp + sizeof(uintptr_t) + tydesc->size);
338 n_obj_params &= 0x7fffffff;
339 first_param = (const type_desc **)(dp + sizeof(uintptr_t));
342 DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n",
343 (unsigned long)n_obj_params, tydesc,
344 dp + sizeof(uintptr_t) * 2);
345 first_param = (const type_desc **)(dp + sizeof(uintptr_t) * 2);
347 return make(first_param, n_obj_params, arena);
350 return make(tydesc->first_param, tydesc->n_params, arena);
357 #define WALK_NUMBER(c_type) \
358 static_cast<T *>(this)->template walk_number<c_type>()
359 #define WALK_SIMPLE(method) static_cast<T *>(this)->method()
365 case SHAPE_U8: WALK_NUMBER(uint8_t); break;
366 case SHAPE_U16: WALK_NUMBER(uint16_t); break;
367 case SHAPE_U32: WALK_NUMBER(uint32_t); break;
368 case SHAPE_U64: WALK_NUMBER(uint64_t); break;
369 case SHAPE_I8: WALK_NUMBER(int8_t); break;
370 case SHAPE_I16: WALK_NUMBER(int16_t); break;
371 case SHAPE_I32: WALK_NUMBER(int32_t); break;
372 case SHAPE_I64: WALK_NUMBER(int64_t); break;
373 case SHAPE_F32: WALK_NUMBER(float); break;
374 case SHAPE_F64: WALK_NUMBER(double); break;
375 case SHAPE_VEC: walk_vec(); break;
376 case SHAPE_TAG: walk_tag(); break;
377 case SHAPE_BOX: walk_box(); break;
378 case SHAPE_STRUCT: walk_struct(); break;
379 case SHAPE_FN: WALK_SIMPLE(walk_fn); break;
380 case SHAPE_OBJ: WALK_SIMPLE(walk_obj); break;
381 case SHAPE_RES: walk_res(); break;
382 case SHAPE_VAR: walk_var(); break;
383 case SHAPE_UNIQ: walk_uniq(); break;
390 ctxt<T>::walk_reset() {
391 const uint8_t *old_sp = sp;
398 ctxt<T>::get_size_align(const uint8_t *&addr) {
400 result.size = get_u16_bump(addr);
401 result.alignment = *addr++;
405 // Returns a pointer to the beginning and a pointer to the end of the shape of
406 // the tag variant with the given ID.
408 std::pair<const uint8_t *,const uint8_t *>
409 ctxt<T>::get_variant_sp(tag_info &tinfo, tag_variant_t variant_id) {
410 uint16_t variant_offset = get_u16(tinfo.info_ptr +
411 variant_id * sizeof(uint16_t));
412 const uint8_t *variant_ptr = tables->tags + variant_offset;
413 uint16_t variant_len = get_u16_bump(variant_ptr);
414 const uint8_t *variant_end = variant_ptr + variant_len;
415 return std::make_pair(variant_ptr, variant_end);
420 ctxt<T>::walk_vec() {
423 uint16_t sp_size = get_u16_bump(sp);
424 const uint8_t *end_sp = sp + sp_size;
426 static_cast<T *>(this)->walk_vec(is_pod, sp_size);
433 ctxt<T>::walk_tag() {
435 tinfo.tag_id = get_u16_bump(sp);
437 // Determine the info pointer.
438 uint16_t info_offset = get_u16(tables->tags +
439 tinfo.tag_id * sizeof(uint16_t));
440 tinfo.info_ptr = tables->tags + info_offset;
442 tinfo.variant_count = get_u16_bump(tinfo.info_ptr);
444 // Determine the largest-variants pointer.
445 uint16_t largest_variants_offset = get_u16_bump(tinfo.info_ptr);
446 tinfo.largest_variants_ptr = tables->tags + largest_variants_offset;
448 // Determine the size and alignment.
449 tinfo.tag_sa = get_size_align(tinfo.info_ptr);
451 // Determine the number of parameters.
452 tinfo.n_params = get_u16_bump(sp);
454 // Read in the tag type parameters.
455 type_param params[tinfo.n_params];
456 for (uint16_t i = 0; i < tinfo.n_params; i++) {
457 uint16_t len = get_u16_bump(sp);
462 tinfo.params = params;
464 // Call to the implementation.
465 static_cast<T *>(this)->walk_tag(tinfo);
470 ctxt<T>::walk_box() {
471 uint16_t sp_size = get_u16_bump(sp);
472 const uint8_t *end_sp = sp + sp_size;
474 static_cast<T *>(this)->walk_box();
481 ctxt<T>::walk_uniq() {
482 uint16_t sp_size = get_u16_bump(sp);
483 const uint8_t *end_sp = sp + sp_size;
485 static_cast<T *>(this)->walk_uniq();
492 ctxt<T>::walk_struct() {
493 uint16_t sp_size = get_u16_bump(sp);
494 const uint8_t *end_sp = sp + sp_size;
496 static_cast<T *>(this)->walk_struct(end_sp);
503 ctxt<T>::walk_res() {
504 uint16_t dtor_offset = get_u16_bump(sp);
505 const rust_fn **resources =
506 reinterpret_cast<const rust_fn **>(tables->resources);
507 const rust_fn *dtor = resources[dtor_offset];
509 uint16_t n_ty_params = get_u16_bump(sp);
511 // Read in the tag type parameters.
512 type_param params[n_ty_params];
513 for (uint16_t i = 0; i < n_ty_params; i++) {
514 uint16_t ty_param_len = get_u16_bump(sp);
515 const uint8_t *next_sp = sp + ty_param_len;
520 uint16_t sp_size = get_u16_bump(sp);
521 const uint8_t *end_sp = sp + sp_size;
523 static_cast<T *>(this)->walk_res(dtor, n_ty_params, params, end_sp);
530 ctxt<T>::walk_var() {
531 uint8_t param = *sp++;
532 static_cast<T *>(this)->walk_var(param);
535 // A shape printer, useful for debugging
537 class print : public ctxt<print> {
540 print(const ctxt<T> &other,
541 const uint8_t *in_sp = NULL,
542 const type_param *in_params = NULL,
543 const rust_shape_tables *in_tables = NULL)
544 : ctxt<print>(other, in_sp, in_params, in_tables) {}
546 print(rust_task *in_task,
548 const uint8_t *in_sp,
549 const type_param *in_params,
550 const rust_shape_tables *in_tables)
551 : ctxt<print>(in_task, in_align, in_sp, in_params, in_tables) {}
553 void walk_tag(tag_info &tinfo);
554 void walk_struct(const uint8_t *end_sp);
555 void walk_res(const rust_fn *dtor, unsigned n_params,
556 const type_param *params, const uint8_t *end_sp);
557 void walk_var(uint8_t param);
559 void walk_vec(bool is_pod, uint16_t sp_size) {
560 DPRINT("vec<"); walk(); DPRINT(">");
563 DPRINT("box<"); walk(); DPRINT(">");
566 void walk_fn() { DPRINT("fn"); }
567 void walk_obj() { DPRINT("obj"); }
571 void walk_number() {}
574 static void print_cx(const T *cx) {
583 // Size-of (which also computes alignment). Be warned: this is an expensive
586 // TODO: Maybe dynamic_size_of() should call into this somehow?
589 class size_of : public ctxt<size_of> {
594 size_of(const size_of &other,
595 const uint8_t *in_sp = NULL,
596 const type_param *in_params = NULL,
597 const rust_shape_tables *in_tables = NULL)
598 : ctxt<size_of>(other, in_sp, in_params, in_tables) {}
601 size_of(const ctxt<T> &other,
602 const uint8_t *in_sp = NULL,
603 const type_param *in_params = NULL,
604 const rust_shape_tables *in_tables = NULL)
605 : ctxt<size_of>(other, in_sp, in_params, in_tables) {}
607 void walk_tag(tag_info &tinfo);
608 void walk_struct(const uint8_t *end_sp);
610 void walk_box() { sa.set(sizeof(void *), sizeof(void *)); }
611 void walk_fn() { sa.set(sizeof(void *)*2, sizeof(void *)); }
612 void walk_obj() { sa.set(sizeof(void *)*2, sizeof(void *)); }
615 void walk_vec(bool is_pod, uint16_t sp_size) {
616 sa.set(sizeof(void *), sizeof(void *));
619 void walk_var(uint8_t param_index) {
620 const type_param *param = ¶ms[param_index];
621 size_of sub(*this, param->shape, param->params, param->tables);
626 void walk_res(const rust_fn *dtor, unsigned n_params,
627 const type_param *params, const uint8_t *end_sp) {
632 void walk_number() { sa.set(sizeof(T), alignof<T>()); }
634 void compute_tag_size(tag_info &tinfo);
637 static void compute_tag_size(const ctxt<T> &other_cx, tag_info &tinfo) {
638 size_of cx(other_cx);
639 cx.compute_tag_size(tinfo);
643 static size_align get(const ctxt<T> &other_cx, unsigned back_up = 0) {
644 size_of cx(other_cx, other_cx.sp - back_up);
647 assert(cx.sa.alignment > 0);
653 // Pointer wrappers for data traversals
661 struct data { typedef T t; };
664 ptr(uint8_t *in_p) : p(in_p) {}
665 ptr(uintptr_t in_p) : p((uint8_t *)in_p) {}
667 inline ptr operator+(const size_t amount) const {
668 return make(p + amount);
670 inline ptr &operator+=(const size_t amount) { p += amount; return *this; }
671 inline bool operator<(const ptr other) { return p < other.p; }
672 inline ptr operator++() { ptr rv(*this); p++; return rv; }
673 inline uint8_t operator*() { return *p; }
676 inline operator T *() { return (T *)p; }
678 inline operator bool() const { return p != NULL; }
679 inline operator uintptr_t() const { return (uintptr_t)p; }
681 static inline ptr make(uint8_t *in_p) {
702 // Pointer pairs for structural comparison
710 data_pair(T &in_fst, T &in_snd) : fst(in_fst), snd(in_snd) {}
712 inline void operator=(const T rhs) { fst = snd = rhs; }
714 static data_pair<T> make(T &fst, T &snd) {
715 data_pair<T> data(fst, snd);
725 struct data { typedef data_pair<T> t; };
727 ptr_pair() : fst(NULL), snd(NULL) {}
728 ptr_pair(uint8_t *in_fst, uint8_t *in_snd) : fst(in_fst), snd(in_snd) {}
729 ptr_pair(data_pair<uint8_t *> &other) : fst(other.fst), snd(other.snd) {}
731 inline void operator=(uint8_t *rhs) { fst = snd = rhs; }
733 inline operator bool() const { return fst != NULL && snd != NULL; }
735 inline ptr_pair operator+(size_t n) const {
736 return make(fst + n, snd + n);
739 inline ptr_pair operator+=(size_t n) {
744 inline ptr_pair operator-(size_t n) const {
745 return make(fst - n, snd - n);
748 inline bool operator<(const ptr_pair &other) const {
749 return fst < other.fst && snd < other.snd;
752 static inline ptr_pair make(uint8_t *fst, uint8_t *snd) {
753 ptr_pair self(fst, snd);
757 static inline ptr_pair make(const data_pair<uint8_t *> &pair) {
758 ptr_pair self(pair.fst, pair.snd);
763 // NB: This function does not align.
766 bump_dp(ptr_pair &ptr) {
767 data_pair<T> data(*reinterpret_cast<T *>(ptr.fst),
768 *reinterpret_cast<T *>(ptr.snd));
775 get_dp(ptr_pair &ptr) {
776 data_pair<T> data(*reinterpret_cast<T *>(ptr.fst),
777 *reinterpret_cast<T *>(ptr.snd));
781 } // end namespace shape
784 inline shape::ptr_pair
785 align_to(const shape::ptr_pair &pair, size_t n) {
786 return shape::ptr_pair::make(align_to(pair.fst, n),
787 align_to(pair.snd, n));
793 // An abstract class (again using the curiously recurring template pattern)
794 // for methods that actually manipulate the data involved.
796 #define ALIGN_TO(alignment) \
798 dp = align_to(dp, (alignment)); \
799 if (this->end_dp && !(dp < this->end_dp)) \
803 #define DATA_SIMPLE(ty, call) \
804 ALIGN_TO(alignof<ty>()); \
805 U end_dp = dp + sizeof(ty); \
806 static_cast<T *>(this)->call; \
809 template<typename T,typename U>
810 class data : public ctxt< data<T,U> > {
817 void walk_box_contents();
818 void walk_uniq_contents();
819 void walk_fn_contents(ptr &dp);
820 void walk_obj_contents(ptr &dp);
821 void walk_variant(tag_info &tinfo, tag_variant_t variant);
823 static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp);
824 static std::pair<ptr_pair,ptr_pair> get_vec_data_range(ptr_pair &dp);
827 data(rust_task *in_task,
829 const uint8_t *in_sp,
830 const type_param *in_params,
831 const rust_shape_tables *in_tables,
833 : ctxt< data<T,U> >(in_task, in_align, in_sp, in_params, in_tables),
837 void walk_tag(tag_info &tinfo);
839 void walk_struct(const uint8_t *end_sp) {
840 static_cast<T *>(this)->walk_struct(end_sp);
843 void walk_vec(bool is_pod, uint16_t sp_size) {
844 DATA_SIMPLE(void *, walk_vec(is_pod, sp_size));
847 void walk_box() { DATA_SIMPLE(void *, walk_box()); }
849 void walk_uniq() { DATA_SIMPLE(void *, walk_uniq()); }
852 ALIGN_TO(alignof<void *>());
853 U next_dp = dp + sizeof(void *) * 2;
854 static_cast<T *>(this)->walk_fn();
859 ALIGN_TO(alignof<void *>());
860 U next_dp = dp + sizeof(void *) * 2;
861 static_cast<T *>(this)->walk_obj();
865 void walk_res(const rust_fn *dtor, unsigned n_params,
866 const type_param *params, const uint8_t *end_sp) {
867 typename U::template data<uintptr_t>::t live = bump_dp<uintptr_t>(dp);
868 // Delegate to the implementation.
869 static_cast<T *>(this)->walk_res(dtor, n_params, params, end_sp,
873 void walk_var(uint8_t param_index) {
874 const type_param *param = &this->params[param_index];
875 T sub(*static_cast<T *>(this), param->shape, param->params,
877 static_cast<T *>(this)->walk_subcontext(sub);
882 void walk_number() { DATA_SIMPLE(W, walk_number<W>()); }
885 template<typename T,typename U>
887 data<T,U>::walk_box_contents() {
888 typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
890 U ref_count_dp(box_ptr);
891 T sub(*static_cast<T *>(this), ref_count_dp + sizeof(ref_cnt_t));
892 static_cast<T *>(this)->walk_box_contents(sub, ref_count_dp);
895 template<typename T,typename U>
897 data<T,U>::walk_uniq_contents() {
898 typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
900 T sub(*static_cast<T *>(this), data_ptr);
901 static_cast<T *>(this)->walk_uniq_contents(sub);
904 template<typename T,typename U>
906 data<T,U>::walk_variant(tag_info &tinfo, tag_variant_t variant_id) {
907 std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
908 this->get_variant_sp(tinfo, variant_id);
909 static_cast<T *>(this)->walk_variant(tinfo, variant_id,
910 variant_ptr_and_end);
913 template<typename T,typename U>
914 std::pair<uint8_t *,uint8_t *>
915 data<T,U>::get_vec_data_range(ptr dp) {
916 rust_vec* ptr = bump_dp<rust_vec*>(dp);
917 uint8_t* data = &ptr->data[0];
918 return std::make_pair(data, data + ptr->fill);
921 template<typename T,typename U>
922 std::pair<ptr_pair,ptr_pair>
923 data<T,U>::get_vec_data_range(ptr_pair &dp) {
924 std::pair<uint8_t *,uint8_t *> fst = get_vec_data_range(dp.fst);
925 std::pair<uint8_t *,uint8_t *> snd = get_vec_data_range(dp.snd);
926 ptr_pair start(fst.first, snd.first);
927 ptr_pair end(fst.second, snd.second);
928 return std::make_pair(start, end);
931 template<typename T,typename U>
933 data<T,U>::walk_tag(tag_info &tinfo) {
934 size_of::compute_tag_size(*this, tinfo);
936 if (tinfo.variant_count > 1)
937 ALIGN_TO(alignof<tag_align_t>());
939 U end_dp = dp + tinfo.tag_sa.size;
941 typename U::template data<tag_variant_t>::t tag_variant;
942 if (tinfo.variant_count > 1)
943 tag_variant = bump_dp<tag_variant_t>(dp);
947 static_cast<T *>(this)->walk_tag(tinfo, tag_variant);
952 template<typename T,typename U>
954 data<T,U>::walk_fn_contents(ptr &dp) {
955 dp += sizeof(void *); // Skip over the code pointer.
957 uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
961 type_desc *subtydesc =
962 *reinterpret_cast<type_desc **>(box_ptr + sizeof(void *));
963 ptr closure_dp(box_ptr + sizeof(void *));
966 type_param *params = type_param::from_fn_shape(subtydesc->shape,
969 closure_dp += sizeof(void *);
970 T sub(*static_cast<T *>(this), subtydesc->shape, params,
971 subtydesc->shape_tables, closure_dp);
976 template<typename T,typename U>
978 data<T,U>::walk_obj_contents(ptr &dp) {
979 dp += sizeof(void *); // Skip over the vtable.
981 uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
982 type_desc *subtydesc =
983 *reinterpret_cast<type_desc **>(box_ptr + sizeof(void *));
984 ptr obj_closure_dp(box_ptr + sizeof(void *));
985 if (!box_ptr) // Null check.
989 type_param *params = type_param::from_obj_shape(subtydesc->shape,
990 obj_closure_dp, arena);
991 T sub(*static_cast<T *>(this), subtydesc->shape, params,
992 subtydesc->shape_tables, obj_closure_dp);
998 // Polymorphic logging, for convenience
1000 class log : public data<log,ptr> {
1001 friend class data<log,ptr>;
1009 const uint8_t *in_sp,
1010 const type_param *in_params,
1011 const rust_shape_tables *in_tables = NULL)
1012 : data<log,ptr>(other.task,
1016 in_tables ? in_tables : other.tables,
1022 const uint8_t *in_sp,
1023 const type_param *in_params,
1024 const rust_shape_tables *in_tables,
1026 : data<log,ptr>(other.task,
1035 log(log &other, ptr in_dp)
1036 : data<log,ptr>(other.task,
1045 void walk_vec(bool is_pod, uint16_t sp_size) {
1046 if (!get_dp<void *>(dp))
1047 out << prefix << "(null)";
1049 walk_vec(is_pod, get_vec_data_range(dp));
1052 void walk_tag(tag_info &tinfo, tag_variant_t tag_variant) {
1053 out << prefix << "tag" << tag_variant;
1054 data<log,ptr>::walk_variant(tinfo, tag_variant);
1058 out << prefix << "@";
1060 data<log,ptr>::walk_box_contents();
1064 out << prefix << "~";
1066 data<log,ptr>::walk_uniq_contents();
1070 out << prefix << "fn";
1072 data<log,ptr>::walk_fn_contents(dp);
1076 out << prefix << "obj";
1078 data<log,ptr>::walk_obj_contents(dp);
1081 void walk_subcontext(log &sub) { sub.walk(); }
1083 void walk_box_contents(log &sub, ptr &ref_count_dp) {
1085 if (!ref_count_dp) {
1093 void walk_uniq_contents(log &sub) {
1099 void walk_struct(const uint8_t *end_sp);
1100 void walk_vec(bool is_pod, const std::pair<ptr,ptr> &data);
1101 void walk_variant(tag_info &tinfo, tag_variant_t variant_id,
1102 const std::pair<const uint8_t *,const uint8_t *>
1103 variant_ptr_and_end);
1104 void walk_string(const std::pair<ptr,ptr> &data);
1105 void walk_res(const rust_fn *dtor, unsigned n_params,
1106 const type_param *params, const uint8_t *end_sp, bool live);
1108 template<typename T>
1109 inline void walk_number() {
1111 fmt_number(out, get_dp<T>(dp));
1115 log(rust_task *in_task,
1117 const uint8_t *in_sp,
1118 const type_param *in_params,
1119 const rust_shape_tables *in_tables,
1121 std::ostream &in_out)
1122 : data<log,ptr>(in_task, in_align, in_sp, in_params, in_tables, in_data),
1127 } // end namespace shape