rt: Remove shape code

This commit is contained in:
Brian Anderson
2012-11-05 13:43:32 -08:00
parent bc3f89e92b
commit 53ec6c3f9b
7 changed files with 8 additions and 1928 deletions
-1
View File
@@ -69,7 +69,6 @@ RUNTIME_CXXS_$(1) := \
rt/isaac/randport.cpp \
rt/miniz.cpp \
rt/rust_kernel.cpp \
rt/rust_shape.cpp \
rt/rust_abi.cpp \
rt/rust_debug.cpp \
rt/memory_region.cpp \
-542
View File
@@ -1,542 +0,0 @@
// Functions that interpret the shape of a type to perform various low-level
// actions, such as copying, freeing, comparing, and so on.
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <utility>
#include "rust_task.h"
#include "rust_shape.h"
namespace shape {
using namespace shape;
// Constants
const uint8_t CMP_EQ = 0u;
const uint8_t CMP_LT = 1u;
const uint8_t CMP_LE = 2u;
// A shape printer, useful for debugging
void
print::walk_tag1(tag_info &tinfo) {
DPRINT("tag%u", tinfo.tag_id);
}
void
print::walk_struct1(const uint8_t *end_sp) {
DPRINT("(");
bool first = true;
while (sp != end_sp) {
if (!first)
DPRINT(",");
first = false;
walk();
}
DPRINT(")");
}
void
print::walk_res1(const rust_fn *dtor, const uint8_t *end_sp) {
DPRINT("res@%p", dtor);
// Print arguments.
if (sp == end_sp)
return;
DPRINT("(");
bool first = true;
while (sp != end_sp) {
if (!first)
DPRINT(",");
first = false;
walk();
}
DPRINT(")");
}
template<>
void print::walk_number1<uint8_t>() { DPRINT("u8"); }
template<>
void print::walk_number1<uint16_t>() { DPRINT("u16"); }
template<>
void print::walk_number1<uint32_t>() { DPRINT("u32"); }
template<>
void print::walk_number1<uint64_t>() { DPRINT("u64"); }
template<>
void print::walk_number1<int8_t>() { DPRINT("i8"); }
template<>
void print::walk_number1<int16_t>() { DPRINT("i16"); }
template<>
void print::walk_number1<int32_t>() { DPRINT("i32"); }
template<>
void print::walk_number1<int64_t>() { DPRINT("i64"); }
template<>
void print::walk_number1<float>() { DPRINT("f32"); }
template<>
void print::walk_number1<double>() { DPRINT("f64"); }
void
size_of::compute_tag_size(tag_info &tinfo) {
// If the precalculated size and alignment are good, use them.
if (tinfo.tag_sa.is_set())
return;
uint16_t n_largest_variants = get_u16_bump(tinfo.largest_variants_ptr);
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);
std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
get_variant_sp(tinfo, variant_id);
const uint8_t *variant_ptr = variant_ptr_and_end.first;
const uint8_t *variant_end = variant_ptr_and_end.second;
size_of sub(*this, variant_ptr, NULL);
sub.align = false;
// Compute the size of this variant.
size_align variant_sa;
bool first = true;
while (sub.sp != variant_end) {
if (!first)
variant_sa.size = align_to(variant_sa.size, sub.sa.alignment);
sub.walk();
sub.align = true, first = false;
variant_sa.add(sub.sa.size, sub.sa.alignment);
}
if (tinfo.tag_sa.size < variant_sa.size)
tinfo.tag_sa = variant_sa;
}
if (tinfo.variant_count == 1) {
if (!tinfo.tag_sa.size)
tinfo.tag_sa.set(1, 1);
} else {
// Add in space for the tag.
tinfo.tag_sa.add(sizeof(tag_variant_t), rust_alignof<tag_align_t>());
}
}
void
size_of::walk_tag1(tag_info &tinfo) {
compute_tag_size(*this, tinfo);
sa = tinfo.tag_sa;
}
void
size_of::walk_struct1(const uint8_t *end_sp) {
size_align struct_sa(0, 1);
bool first = true;
while (sp != end_sp) {
if (!first)
struct_sa.size = align_to(struct_sa.size, sa.alignment);
walk();
align = true, first = false;
struct_sa.add(sa);
}
sa = struct_sa;
}
// Copy constructors
#if 0
class copy : public data<copy,uint8_t *> {
// FIXME #2892
};
#endif
// Structural comparison glue.
class cmp : public data<cmp,ptr_pair> {
friend class data<cmp,ptr_pair>;
private:
void walk_slice2(bool is_pod,
const std::pair<ptr_pair,ptr_pair> &data_range);
void walk_vec2(bool is_pod,
const std::pair<ptr_pair,ptr_pair> &data_range);
inline void walk_subcontext2(cmp &sub) {
sub.walk();
result = sub.result;
}
inline void walk_box_contents2(cmp &sub) {
sub.align = true;
sub.walk();
result = sub.result;
}
inline void walk_uniq_contents2(cmp &sub) {
sub.align = true;
sub.walk();
result = sub.result;
}
inline void walk_rptr_contents2(cmp &sub) {
sub.align = true;
sub.walk();
result = sub.result;
}
inline void cmp_two_pointers() {
ALIGN_TO(rust_alignof<void *>());
data_pair<uint8_t *> fst = bump_dp<uint8_t *>(dp);
data_pair<uint8_t *> snd = bump_dp<uint8_t *>(dp);
cmp_number(fst);
if (!result)
cmp_number(snd);
}
inline void cmp_pointer() {
ALIGN_TO(rust_alignof<void *>());
cmp_number(bump_dp<uint8_t *>(dp));
}
template<typename T>
void cmp_number(const data_pair<T> &nums) {
result = (nums.fst < nums.snd) ? -1 : (nums.fst == nums.snd) ? 0 : 1;
}
public:
int result;
cmp(rust_task *in_task,
bool in_align,
const uint8_t *in_sp,
const rust_shape_tables *in_tables,
uint8_t *in_data_0,
uint8_t *in_data_1)
: data<cmp,ptr_pair>(in_task, in_align, in_sp, in_tables,
ptr_pair::make(in_data_0, in_data_1)),
result(0) {}
cmp(const cmp &other,
const uint8_t *in_sp,
const rust_shape_tables *in_tables,
ptr_pair &in_dp)
: data<cmp,ptr_pair>(other.task, other.align, in_sp, in_tables,
in_dp),
result(0) {}
cmp(const cmp &other,
const uint8_t *in_sp = NULL,
const rust_shape_tables *in_tables = NULL)
: data<cmp,ptr_pair>(other.task,
other.align,
in_sp ? in_sp : other.sp,
in_tables ? in_tables : other.tables,
other.dp),
result(0) {}
cmp(const cmp &other, const ptr_pair &in_dp)
: data<cmp,ptr_pair>(other.task,
other.align,
other.sp,
other.tables,
in_dp),
result(0) {}
void walk_vec2(bool is_pod) {
walk_vec2(is_pod, get_vec_data_range(dp));
}
void walk_unboxed_vec2(bool is_pod) {
walk_vec2(is_pod, get_unboxed_vec_data_range(dp));
}
void walk_slice2(bool is_pod, bool is_str) {
// Slices compare just like vecs.
walk_vec2(is_pod, get_slice_data_range(is_str, dp));
}
void walk_fixedvec2(uint16_t n_elts, size_t elt_sz, bool is_pod) {
// Fixedvecs compare just like vecs.
walk_vec2(is_pod, get_fixedvec_data_range(n_elts, elt_sz, dp));
}
void walk_box2() {
data<cmp,ptr_pair>::walk_box_contents1();
}
void walk_uniq2() {
data<cmp,ptr_pair>::walk_uniq_contents1();
}
void walk_rptr2() {
data<cmp,ptr_pair>::walk_rptr_contents1();
}
void walk_trait2() {
data<cmp,ptr_pair>::walk_box_contents1();
}
void walk_tydesc2(char) {
cmp_pointer();
}
void walk_fn2(char) { return cmp_two_pointers(); }
void walk_obj2() { return cmp_two_pointers(); }
void walk_tag2(tag_info &tinfo,
const data_pair<tag_variant_t> &tag_variants);
void walk_struct2(const uint8_t *end_sp);
void walk_res2(const rust_fn *dtor, const uint8_t *end_sp);
void walk_variant2(tag_info &tinfo,
tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
template<typename T>
void walk_number2() { cmp_number(get_dp<T>(dp)); }
};
template<>
void cmp::cmp_number<int32_t>(const data_pair<int32_t> &nums) {
result = (nums.fst < nums.snd) ? -1 : (nums.fst == nums.snd) ? 0 : 1;
}
void
cmp::walk_vec2(bool is_pod, const std::pair<ptr_pair,ptr_pair> &data_range) {
cmp sub(*this, data_range.first);
ptr_pair data_end = sub.end_dp = data_range.second;
while (!result && sub.dp < data_end) {
sub.walk_reset();
result = sub.result;
sub.align = true;
}
if (!result) {
// If we hit the end, the result comes down to length comparison.
int len_fst = data_range.second.fst - data_range.first.fst;
int len_snd = data_range.second.snd - data_range.first.snd;
cmp_number(data_pair<int>::make(len_fst, len_snd));
}
}
void
cmp::walk_tag2(tag_info &tinfo,
const data_pair<tag_variant_t> &tag_variants) {
cmp_number(tag_variants);
if (result != 0)
return;
data<cmp,ptr_pair>::walk_variant1(tinfo, tag_variants.fst);
}
void
cmp::walk_struct2(const uint8_t *end_sp) {
while (!result && this->sp != end_sp) {
this->walk();
align = true;
}
}
void
cmp::walk_res2(const rust_fn *dtor, const uint8_t *end_sp) {
this->cmp_two_pointers();
}
void
cmp::walk_variant2(tag_info &tinfo,
tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
cmp sub(*this, variant_ptr_and_end.first);
const uint8_t *variant_end = variant_ptr_and_end.second;
while (!result && sub.sp < variant_end) {
sub.walk();
result = sub.result;
sub.align = true;
}
}
// Polymorphic logging, for convenience
void
log::walk_string2(const std::pair<ptr,ptr> &data) {
out << prefix << "\"" << std::hex;
ptr subdp = data.first;
while (subdp < data.second) {
char ch = *subdp;
switch(ch) {
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
case '\t': out << "\\t"; break;
case '\\': out << "\\\\"; break;
case '"': out << "\\\""; break;
default:
if (isprint(ch)) {
out << ch;
} else if (ch) {
out << "\\x" << std::setw(2) << std::setfill('0')
<< (unsigned int)(unsigned char)ch;
}
}
++subdp;
}
out << "\"" << std::dec;
}
void
log::walk_struct2(const uint8_t *end_sp) {
out << prefix << "(";
prefix = "";
bool first = true;
while (sp != end_sp) {
if (!first)
out << ", ";
walk();
align = true, first = false;
}
out << ")";
}
void
log::walk_vec2(bool is_pod, const std::pair<ptr,ptr> &data) {
if (peek() == SHAPE_U8) {
sp++; // It's a string. We handle this ourselves.
walk_string2(data);
return;
}
out << prefix << "[";
log sub(*this, data.first);
sub.end_dp = data.second;
while (sub.dp < data.second) {
sub.walk_reset();
sub.align = true;
sub.prefix = ", ";
}
out << "]";
}
void
log::walk_variant2(tag_info &tinfo,
tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
log sub(*this, variant_ptr_and_end.first);
const uint8_t *variant_end = variant_ptr_and_end.second;
bool first = true;
while (sub.sp < variant_end) {
out << (first ? "(" : ", ");
sub.walk();
sub.align = true, first = false;
}
if (!first)
out << ")";
}
void
log::walk_res2(const rust_fn *dtor, const uint8_t *end_sp) {
out << prefix << "res";
if (this->sp == end_sp)
return;
out << "(";
bool first = true;
while (sp != end_sp) {
if (!first)
out << ", ";
walk();
align = true, first = false;
}
out << ")";
}
} // end namespace shape
extern "C" void
shape_cmp_type(int8_t *result, const type_desc *tydesc,
uint8_t *data_0, uint8_t *data_1, uint8_t cmp_type) {
rust_task *task = rust_get_current_task();
shape::arena arena;
shape::cmp cmp(task, true, tydesc->shape, tydesc->shape_tables,
data_0, data_1);
cmp.walk();
switch (cmp_type) {
case shape::CMP_EQ: *result = cmp.result == 0; break;
case shape::CMP_LT: *result = cmp.result < 0; break;
case shape::CMP_LE: *result = cmp.result <= 0; break;
}
}
extern "C" rust_str *
shape_log_str(const type_desc *tydesc, uint8_t *data) {
rust_task *task = rust_get_current_task();
shape::arena arena;
std::stringstream ss;
shape::log log(task, true, tydesc->shape, tydesc->shape_tables,
data, ss);
log.walk();
int len = ss.str().length();
return make_str(task->kernel, ss.str().c_str(), len, "log_str");
}
extern "C" void
shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
rust_task *task = rust_get_current_task();
shape::arena arena;
std::stringstream ss;
shape::log log(task, true, tydesc->shape, tydesc->shape_tables,
data, ss);
log.walk();
task->sched_loop->get_log().log(task, level, "%s", ss.str().c_str());
}
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
-1314
View File
@@ -1,1314 +0,0 @@
// Functions that interpret the shape of a type to perform various low-level
// actions, such as copying, freeing, comparing, and so on.
#ifndef RUST_SHAPE_H
#define RUST_SHAPE_H
// Tell ISAAC to let go of max() and min() defines.
#undef max
#undef min
#include <iostream>
#include "rust_globals.h"
#include "rust_util.h"
// ISAAC pollutes our namespace.
#undef align
#define ARENA_SIZE 256
//#define DPRINT(fmt,...) fprintf(stderr, fmt, ##__VA_ARGS__)
//#define DPRINTCX(cx) shape::print::print_cx(cx)
#define DPRINT(fmt,...)
#define DPRINTCX(cx)
namespace shape {
typedef unsigned long tag_variant_t;
typedef unsigned long tag_align_t;
// Constants
const uint8_t SHAPE_U8 = 0u;
const uint8_t SHAPE_U16 = 1u;
const uint8_t SHAPE_U32 = 2u;
const uint8_t SHAPE_U64 = 3u;
const uint8_t SHAPE_I8 = 4u;
const uint8_t SHAPE_I16 = 5u;
const uint8_t SHAPE_I32 = 6u;
const uint8_t SHAPE_I64 = 7u;
const uint8_t SHAPE_F32 = 8u;
const uint8_t SHAPE_F64 = 9u;
const uint8_t SHAPE_BOX = 10u;
const uint8_t SHAPE_TAG = 12u;
const uint8_t SHAPE_STRUCT = 17u;
const uint8_t SHAPE_BOX_FN = 18u;
const uint8_t SHAPE_RES = 20u;
const uint8_t SHAPE_UNIQ = 22u;
const uint8_t SHAPE_UNIQ_FN = 25u;
const uint8_t SHAPE_STACK_FN = 26u;
const uint8_t SHAPE_BARE_FN = 27u;
const uint8_t SHAPE_TYDESC = 28u;
const uint8_t SHAPE_SEND_TYDESC = 29u;
const uint8_t SHAPE_RPTR = 31u;
const uint8_t SHAPE_FIXEDVEC = 32u;
const uint8_t SHAPE_SLICE = 33u;
const uint8_t SHAPE_UNBOXED_VEC = 34u;
#ifdef _LP64
const uint8_t SHAPE_PTR = SHAPE_U64;
#else
const uint8_t SHAPE_PTR = SHAPE_U32;
#endif
// Forward declarations
struct rust_obj;
struct size_align;
class ptr;
// Arenas; these functions must execute very quickly, so we use an arena
// instead of malloc or new.
class arena {
uint8_t *ptr;
uint8_t data[ARENA_SIZE];
public:
arena() : ptr(data) {}
template<typename T>
inline T *alloc(size_t count = 1) {
// FIXME: align (probably won't fix before #1498)
size_t sz = count * sizeof(T);
T *rv = (T *)ptr;
ptr += sz;
if (ptr > &data[ARENA_SIZE]) {
fprintf(stderr, "Arena space exhausted, sorry\n");
abort();
}
return rv;
}
};
// Alignment inquiries
//
// We can't directly use __alignof__ everywhere because that returns the
// preferred alignment of the type, which is different from the ABI-mandated
// alignment of the type in some cases (e.g. doubles on x86). The latter is
// what actually gets used for struct elements.
template<typename T>
inline size_t
rust_alignof() {
#ifdef _MSC_VER
return __alignof(T);
#else
return __alignof__(T);
#endif
}
template<>
inline size_t
rust_alignof<double>() {
return 4;
}
// Issue #2303
// On 32-bit x86 the alignment of 64-bit ints in structures is 4 bytes
// Which is different from the preferred 8-byte alignment reported
// by __alignof__ (at least on gcc).
#ifndef __WIN32__
#ifdef __i386__
template<>
inline size_t
rust_alignof<uint64_t>() {
return 4;
}
#endif
#endif
// Utility classes
struct size_align {
size_t size;
size_t alignment;
size_align(size_t in_size = 0, size_t in_align = 1) :
size(in_size), alignment(in_align) {}
bool is_set() const { return alignment != 0; }
inline void set(size_t in_size, size_t in_align) {
size = in_size;
alignment = in_align;
}
inline void add(const size_align &other) {
add(other.size, other.alignment);
}
inline void add(size_t extra_size, size_t extra_align) {
size += extra_size;
alignment = std::max(alignment, extra_align);
}
static inline size_align make(size_t in_size) {
size_align sa;
sa.size = sa.alignment = in_size;
return sa;
}
static inline size_align make(size_t in_size, size_t in_align) {
size_align sa;
sa.size = in_size;
sa.alignment = in_align;
return sa;
}
};
struct tag_info {
uint16_t tag_id; // The tag ID.
const uint8_t *info_ptr; // Pointer to the info table.
uint16_t variant_count; // Number of variants in the tag.
const uint8_t *largest_variants_ptr; // Ptr to largest variants table.
size_align tag_sa; // Size and align of this tag.
};
// Utility functions
inline uint16_t
get_u16(const uint8_t *addr) {
return *reinterpret_cast<const uint16_t *>(addr);
}
inline uint16_t
get_u16_bump(const uint8_t *&addr) {
uint16_t result = get_u16(addr);
addr += sizeof(uint16_t);
return result;
}
template<typename T>
inline void
fmt_number(std::ostream &out, T n) {
out << n;
}
// Override the character interpretation for these two.
template<>
inline void
fmt_number<uint8_t>(std::ostream &out, uint8_t n) {
out << (int)n;
}
template<>
inline void
fmt_number<int8_t>(std::ostream &out, int8_t n) {
out << (int)n;
}
// Contexts
// The base context, an abstract class. We use the curiously recurring
// template pattern here to avoid virtual dispatch.
template<typename T>
class ctxt {
public:
const uint8_t *sp; // shape pointer
const rust_shape_tables *tables;
rust_task *task;
bool align;
ctxt(rust_task *in_task,
bool in_align,
const uint8_t *in_sp,
const rust_shape_tables *in_tables)
: sp(in_sp),
tables(in_tables),
task(in_task),
align(in_align) {}
template<typename U>
ctxt(const ctxt<U> &other,
const uint8_t *in_sp = NULL,
const rust_shape_tables *in_tables = NULL)
: sp(in_sp ? in_sp : other.sp),
tables(in_tables ? in_tables : other.tables),
task(other.task),
align(other.align) {}
void walk();
void walk_reset();
std::pair<const uint8_t *,const uint8_t *>
get_variant_sp(tag_info &info, tag_variant_t variant_id);
const char *
get_variant_name(tag_info &info, tag_variant_t variant_id);
protected:
inline uint8_t peek() { return *sp; }
inline size_align get_size_align(const uint8_t *&addr);
private:
void walk_vec0();
void walk_unboxed_vec0();
void walk_tag0();
void walk_box0();
void walk_uniq0();
void walk_struct0();
void walk_res0();
void walk_rptr0();
void walk_fixedvec0();
void walk_slice0();
};
// Core Rust types
struct rust_fn {
void (*code)(uint8_t *rv, rust_task *task, void *env, ...);
void *env;
};
// Traversals
#define WALK_NUMBER(c_type) \
static_cast<T *>(this)->template walk_number1<c_type>()
#define WALK_SIMPLE(method) static_cast<T *>(this)->method()
template<typename T>
void
ctxt<T>::walk() {
char s = *sp++;
switch (s) {
case SHAPE_U8: WALK_NUMBER(uint8_t); break;
case SHAPE_U16: WALK_NUMBER(uint16_t); break;
case SHAPE_U32: WALK_NUMBER(uint32_t); break;
case SHAPE_U64: WALK_NUMBER(uint64_t); break;
case SHAPE_I8: WALK_NUMBER(int8_t); break;
case SHAPE_I16: WALK_NUMBER(int16_t); break;
case SHAPE_I32: WALK_NUMBER(int32_t); break;
case SHAPE_I64: WALK_NUMBER(int64_t); break;
case SHAPE_F32: WALK_NUMBER(float); break;
case SHAPE_F64: WALK_NUMBER(double); break;
case SHAPE_TAG: walk_tag0(); break;
case SHAPE_BOX: walk_box0(); break;
case SHAPE_STRUCT: walk_struct0(); break;
case SHAPE_RES: walk_res0(); break;
case SHAPE_UNIQ: walk_uniq0(); break;
case SHAPE_BOX_FN:
case SHAPE_UNIQ_FN:
case SHAPE_STACK_FN:
case SHAPE_BARE_FN: static_cast<T*>(this)->walk_fn1(s); break;
case SHAPE_TYDESC:
case SHAPE_SEND_TYDESC: static_cast<T*>(this)->walk_tydesc1(s); break;
case SHAPE_RPTR: walk_rptr0(); break;
case SHAPE_FIXEDVEC: walk_fixedvec0(); break;
case SHAPE_SLICE: walk_slice0(); break;
case SHAPE_UNBOXED_VEC: walk_unboxed_vec0(); break;
default: abort();
}
}
template<typename T>
void
ctxt<T>::walk_reset() {
const uint8_t *old_sp = sp;
walk();
sp = old_sp;
}
template<typename T>
size_align
ctxt<T>::get_size_align(const uint8_t *&addr) {
size_align result;
result.size = get_u16_bump(addr);
result.alignment = *addr++;
return result;
}
// Returns a pointer to the beginning and a pointer to the end of the shape of
// the tag variant with the given ID.
template<typename T>
std::pair<const uint8_t *,const uint8_t *>
ctxt<T>::get_variant_sp(tag_info &tinfo, tag_variant_t variant_id) {
uint16_t variant_offset = get_u16(tinfo.info_ptr +
variant_id * sizeof(uint16_t));
const uint8_t *variant_ptr = tables->tags + variant_offset;
uint16_t variant_len = get_u16_bump(variant_ptr);
const uint8_t *variant_end = variant_ptr + variant_len;
return std::make_pair(variant_ptr, variant_end);
}
template<typename T>
const char *
ctxt<T>::get_variant_name(tag_info &tinfo, tag_variant_t variant_id) {
std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
this->get_variant_sp(tinfo, variant_id);
// skip over the length to get the null-terminated string:
return (const char*)(variant_ptr_and_end.second + 2);
}
template<typename T>
void
ctxt<T>::walk_vec0() {
bool is_pod = *sp++;
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_vec1(is_pod);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_unboxed_vec0() {
bool is_pod = *sp++;
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_unboxed_vec1(is_pod);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_tag0() {
tag_info tinfo;
tinfo.tag_id = get_u16_bump(sp);
// Determine the info pointer.
uint16_t info_offset = get_u16(tables->tags +
tinfo.tag_id * sizeof(uint16_t));
tinfo.info_ptr = tables->tags + info_offset;
tinfo.variant_count = get_u16_bump(tinfo.info_ptr);
// Determine the largest-variants pointer.
uint16_t largest_variants_offset = get_u16_bump(tinfo.info_ptr);
tinfo.largest_variants_ptr = tables->tags + largest_variants_offset;
// Determine the size and alignment.
tinfo.tag_sa = get_size_align(tinfo.info_ptr);
// Call to the implementation.
static_cast<T *>(this)->walk_tag1(tinfo);
}
template<typename T>
void
ctxt<T>::walk_box0() {
static_cast<T *>(this)->walk_box1();
}
template<typename T>
void
ctxt<T>::walk_uniq0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_uniq1();
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_rptr0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_rptr1();
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_fixedvec0() {
uint16_t n_elts = get_u16_bump(sp);
bool is_pod = *sp++;
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_fixedvec1(n_elts, is_pod);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_slice0() {
bool is_pod = *sp++;
bool is_str = *sp++;
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_slice1(is_pod, is_str);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_struct0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_struct1(end_sp);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_res0() {
uint16_t dtor_offset = get_u16_bump(sp);
const rust_fn **resources =
reinterpret_cast<const rust_fn **>(tables->resources);
const rust_fn *dtor = resources[dtor_offset];
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_res1(dtor, end_sp);
sp = end_sp;
}
// A shape printer, useful for debugging
class print : public ctxt<print> {
public:
template<typename T>
print(const ctxt<T> &other,
const uint8_t *in_sp = NULL,
const rust_shape_tables *in_tables = NULL)
: ctxt<print>(other, in_sp, in_tables) {}
print(rust_task *in_task,
bool in_align,
const uint8_t *in_sp,
const rust_shape_tables *in_tables)
: ctxt<print>(in_task, in_align, in_sp, in_tables) {}
void walk_tag1(tag_info &tinfo);
void walk_struct1(const uint8_t *end_sp);
void walk_res1(const rust_fn *dtor, const uint8_t *end_sp);
void walk_vec1(bool is_pod) {
DPRINT("vec<"); walk(); DPRINT(">");
}
void walk_unboxed_vec1(bool is_pod) {
DPRINT("unboxed_vec<"); walk(); DPRINT(">");
}
void walk_uniq1() {
DPRINT("~<"); walk(); DPRINT(">");
}
void walk_box1() {
DPRINT("@<"); walk(); DPRINT(">");
}
void walk_rptr1() {
DPRINT("&<"); walk(); DPRINT(">");
}
void walk_fixedvec1(uint16_t n_elts, bool is_pod) {
DPRINT("fixedvec<%u, ", n_elts); walk(); DPRINT(">");
}
void walk_slice1(bool is_pod, bool is_str) {
DPRINT("slice<"); walk(); DPRINT(">");
}
void walk_fn1(char kind) {
switch(kind) {
case SHAPE_BARE_FN: DPRINT("fn"); break;
case SHAPE_BOX_FN: DPRINT("fn@"); break;
case SHAPE_UNIQ_FN: DPRINT("fn~"); break;
case SHAPE_STACK_FN: DPRINT("fn&"); break;
default: abort();
}
}
void walk_trait1() { DPRINT("trait"); }
void walk_tydesc1(char kind) {
switch(kind) {
case SHAPE_TYDESC: DPRINT("tydesc"); break;
case SHAPE_SEND_TYDESC: DPRINT("send-tydesc"); break;
default: abort();
}
}
template<typename T>
void walk_number1() {}
template<typename T>
static void print_cx(const T *cx) {
print self(*cx);
self.align = false;
self.walk();
}
};
//
// Size-of (which also computes alignment). Be warned: this is an expensive
// operation.
//
// FIXME #2894: Maybe dynamic_size_of() should call into this somehow?
//
class size_of : public ctxt<size_of> {
private:
size_align sa;
public:
size_of(const size_of &other,
const uint8_t *in_sp = NULL,
const rust_shape_tables *in_tables = NULL)
: ctxt<size_of>(other, in_sp, in_tables) {}
template<typename T>
size_of(const ctxt<T> &other,
const uint8_t *in_sp = NULL,
const rust_shape_tables *in_tables = NULL)
: ctxt<size_of>(other, in_sp, in_tables) {}
void walk_tag1(tag_info &tinfo);
void walk_struct1(const uint8_t *end_sp);
void walk_uniq1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_rptr1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_slice1(bool,bool)
{ sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_box1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_fn1(char) { sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_trait1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_tydesc1(char) { sa.set(sizeof(void *), sizeof(void *)); }
void walk_closure1();
void walk_vec1(bool is_pod) {
sa.set(sizeof(void *), sizeof(void *));
}
void walk_unboxed_vec1(bool is_pod) {
assert(false &&
"trying to compute size of dynamically sized unboxed vector");
}
void walk_res1(const rust_fn *dtor, const uint8_t *end_sp) {
abort(); // FIXME #2895
}
void walk_fixedvec1(uint16_t n_elts, bool is_pod) {
size_of sub(*this);
sub.walk();
sa.set(sub.sa.size * n_elts, sub.sa.alignment);
}
template<typename T>
void walk_number1() { sa.set(sizeof(T), rust_alignof<T>()); }
void compute_tag_size(tag_info &tinfo);
template<typename T>
static void compute_tag_size(const ctxt<T> &other_cx, tag_info &tinfo) {
size_of cx(other_cx);
cx.compute_tag_size(tinfo);
}
template<typename T>
static size_align get(const ctxt<T> &other_cx, unsigned back_up = 0) {
size_of cx(other_cx, other_cx.sp - back_up);
cx.align = false;
cx.walk();
assert(cx.sa.alignment > 0);
return cx.sa;
}
};
// Pointer wrappers for data traversals
class ptr {
private:
uint8_t *p;
public:
template<typename T>
struct data { typedef T t; };
ptr() : p(NULL) {}
explicit ptr(uint8_t *in_p) : p(in_p) {}
explicit ptr(uintptr_t in_p) : p((uint8_t *)in_p) {}
inline ptr operator+(const size_t amount) const {
return make(p + amount);
}
inline ptr &operator+=(const size_t amount) { p += amount; return *this; }
inline bool operator<(const ptr other) { return p < other.p; }
inline ptr operator++() { ptr rv(*this); p++; return rv; }
inline uint8_t operator*() { return *p; }
template<typename T>
inline operator T *() { return (T *)p; }
inline operator bool() const { return p != NULL; }
inline operator uintptr_t() const { return (uintptr_t)p; }
inline const type_desc *box_body_td() const {
rust_opaque_box *box = *reinterpret_cast<rust_opaque_box**>(p);
assert(box->ref_count >= 1);
return box->td;
}
inline const type_desc *uniq_body_td() const {
rust_opaque_box *box = *reinterpret_cast<rust_opaque_box**>(p);
return box->td;
}
inline ptr box_body() const {
rust_opaque_box *box = *reinterpret_cast<rust_opaque_box**>(p);
return make((uint8_t*)::box_body(box));
}
static inline ptr make(uint8_t *in_p) {
ptr self(in_p);
return self;
}
};
template<typename T>
static inline T
bump_dp(ptr &dp) {
T x = *((T *)dp);
dp += sizeof(T);
return x;
}
template<typename T>
static inline T
get_dp(ptr dp) {
return *((T *)dp);
}
// Pointer pairs for structural comparison
template<typename T>
class data_pair {
public:
T fst, snd;
data_pair() {}
data_pair(T &in_fst, T &in_snd) : fst(in_fst), snd(in_snd) {}
inline void operator=(const T rhs) { fst = snd = rhs; }
static data_pair<T> make(T &fst, T &snd) {
data_pair<T> data(fst, snd);
return data;
}
};
class ptr_pair {
public:
uint8_t *fst, *snd;
template<typename T>
struct data { typedef data_pair<T> t; };
ptr_pair() : fst(NULL), snd(NULL) {}
ptr_pair(uint8_t *in_fst, uint8_t *in_snd) : fst(in_fst), snd(in_snd) {}
ptr_pair(data_pair<uint8_t *> &other) : fst(other.fst), snd(other.snd) {}
inline void operator=(uint8_t *rhs) { fst = snd = rhs; }
inline operator bool() const { return fst != NULL && snd != NULL; }
inline ptr_pair operator+(size_t n) const {
return make(fst + n, snd + n);
}
inline ptr_pair operator+=(size_t n) {
fst += n; snd += n;
return *this;
}
inline ptr_pair operator-(size_t n) const {
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;
}
static inline ptr_pair make(const data_pair<uint8_t *> &pair) {
ptr_pair self(pair.fst, pair.snd);
return self;
}
inline const type_desc *box_body_td() const {
// Here we assume that the two ptrs are both boxes with
// equivalent type descriptors. This is safe because we only
// use ptr_pair in the cmp glue, and we only use the cmp glue
// when rust guarantees us that the boxes are of the same
// type. As box types are not opaque to Rust, it is in a
// position to make this determination.
rust_opaque_box *box_fst = *reinterpret_cast<rust_opaque_box**>(fst);
assert(box_fst->ref_count >= 1);
return box_fst->td;
}
inline const type_desc *uniq_body_td() const {
rust_opaque_box *box_fst = *reinterpret_cast<rust_opaque_box**>(fst);
return box_fst->td;
}
inline ptr_pair box_body() const {
rust_opaque_box *box_fst = *reinterpret_cast<rust_opaque_box**>(fst);
rust_opaque_box *box_snd = *reinterpret_cast<rust_opaque_box**>(snd);
return make((uint8_t*)::box_body(box_fst),
(uint8_t*)::box_body(box_snd));
}
};
// NB: This function does not align.
template<typename T>
inline data_pair<T>
bump_dp(ptr_pair &ptr) {
data_pair<T> data(*reinterpret_cast<T *>(ptr.fst),
*reinterpret_cast<T *>(ptr.snd));
ptr += sizeof(T);
return data;
}
template<typename T>
inline data_pair<T>
get_dp(ptr_pair &ptr) {
data_pair<T> data(*reinterpret_cast<T *>(ptr.fst),
*reinterpret_cast<T *>(ptr.snd));
return data;
}
} // end namespace shape
inline shape::ptr_pair
align_to(const shape::ptr_pair &pair, size_t n) {
return shape::ptr_pair::make(align_to(pair.fst, n),
align_to(pair.snd, n));
}
namespace shape {
// An abstract class (again using the curiously recurring template pattern)
// for methods that actually manipulate the data involved.
#define ALIGN_TO(alignment) \
if (this->align) { \
dp = align_to(dp, (alignment)); \
if (this->end_dp && !(dp < this->end_dp)) \
return; \
}
#define DATA_SIMPLE(ty, call) \
ALIGN_TO(rust_alignof<ty>()); \
U end_dp = dp + sizeof(ty); \
static_cast<T *>(this)->call; \
dp = end_dp;
template<typename T,typename U>
class data : public ctxt< data<T,U> > {
public:
U dp;
protected:
U end_dp;
void walk_box_contents1();
void walk_uniq_contents1();
void walk_rptr_contents1();
void walk_fn_contents1();
void walk_trait_contents1();
void walk_variant1(tag_info &tinfo, tag_variant_t variant);
static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp);
static std::pair<ptr_pair,ptr_pair> get_vec_data_range(ptr_pair &dp);
static std::pair<uint8_t *,uint8_t *> get_unboxed_vec_data_range(ptr dp);
static std::pair<ptr_pair,ptr_pair>
get_unboxed_vec_data_range(ptr_pair &dp);
static ptr get_unboxed_vec_end(ptr dp);
static ptr_pair get_unboxed_vec_end(ptr_pair &dp);
static std::pair<uint8_t *,uint8_t *> get_slice_data_range(bool is_str,
ptr dp);
static std::pair<ptr_pair,ptr_pair> get_slice_data_range(bool is_str,
ptr_pair &dp);
static std::pair<uint8_t *,uint8_t *>
get_fixedvec_data_range(uint16_t n_elts, size_t elt_sz, ptr dp);
static std::pair<ptr_pair,ptr_pair>
get_fixedvec_data_range(uint16_t n_elts, size_t elt_sz, ptr_pair &dp);
public:
data(rust_task *in_task,
bool in_align,
const uint8_t *in_sp,
const rust_shape_tables *in_tables,
U const &in_dp)
: ctxt< data<T,U> >(in_task, in_align, in_sp, in_tables),
dp(in_dp),
end_dp() {}
void walk_tag1(tag_info &tinfo);
void walk_struct1(const uint8_t *end_sp) {
// FIXME (probably won't fix before #1498): shouldn't we be aligning
// to the first element here?
static_cast<T *>(this)->walk_struct2(end_sp);
}
void walk_vec1(bool is_pod) {
DATA_SIMPLE(void *, walk_vec2(is_pod));
}
void walk_unboxed_vec1(bool is_pod) {
// align?
U next_dp = get_unboxed_vec_end(dp);
static_cast<T *>(this)->walk_unboxed_vec2(is_pod);
dp = next_dp;
}
void walk_slice1(bool is_pod, bool is_str) {
DATA_SIMPLE(void *, walk_slice2(is_pod, is_str));
}
void walk_fixedvec1(uint16_t n_elts, bool is_pod) {
size_align sa = size_of::get(*this);
ALIGN_TO(sa.alignment);
U next_dp = dp + (n_elts * sa.size);
static_cast<T *>(this)->walk_fixedvec2(n_elts, sa.size, is_pod);
dp = next_dp;
}
void walk_box1() { DATA_SIMPLE(void *, walk_box2()); }
void walk_uniq1() { DATA_SIMPLE(void *, walk_uniq2()); }
void walk_rptr1() { DATA_SIMPLE(void *, walk_rptr2()); }
void walk_fn1(char code) {
ALIGN_TO(rust_alignof<void *>());
U next_dp = dp + sizeof(void *) * 2;
static_cast<T *>(this)->walk_fn2(code);
dp = next_dp;
}
void walk_trait1() {
ALIGN_TO(rust_alignof<void *>());
U next_dp = dp + sizeof(void *);
static_cast<T *>(this)->walk_trait2();
dp = next_dp;
}
void walk_tydesc1(char kind) {
ALIGN_TO(rust_alignof<void *>());
U next_dp = dp + sizeof(void *);
static_cast<T *>(this)->walk_tydesc2(kind);
dp = next_dp;
}
void walk_res1(const rust_fn *dtor, const uint8_t *end_sp) {
// Delegate to the implementation.
static_cast<T *>(this)->walk_res2(dtor, end_sp);
}
template<typename WN>
void walk_number1() {
//DATA_SIMPLE(W, walk_number2<W>());
ALIGN_TO(rust_alignof<WN>());
U end_dp = dp + sizeof(WN);
T* t = static_cast<T *>(this);
t->template walk_number2<WN>();
dp = end_dp;
}
};
template<typename T,typename U>
void
data<T,U>::walk_box_contents1() {
const type_desc *body_td = dp.box_body_td();
if (body_td) {
U body_dp(dp.box_body());
arena arena;
T sub(*static_cast<T *>(this), body_td->shape,
body_td->shape_tables, body_dp);
sub.align = true;
static_cast<T *>(this)->walk_box_contents2(sub);
}
}
template<typename T,typename U>
void
data<T,U>::walk_uniq_contents1() {
const type_desc *body_td = dp.uniq_body_td();
if (body_td) {
U body_dp(dp.box_body());
arena arena;
T sub(*static_cast<T *>(this), /*body_td->shape,*/ this->sp,
body_td->shape_tables, body_dp);
sub.align = true;
static_cast<T *>(this)->walk_uniq_contents2(sub);
}
}
template<typename T,typename U>
void
data<T,U>::walk_rptr_contents1() {
typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
U data_ptr(box_ptr);
T sub(*static_cast<T *>(this), data_ptr);
static_cast<T *>(this)->walk_rptr_contents2(sub);
}
template<typename T,typename U>
void
data<T,U>::walk_variant1(tag_info &tinfo, tag_variant_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_variant2(tinfo, variant_id,
variant_ptr_and_end);
}
template<typename T,typename U>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_vec_data_range(ptr dp) {
rust_vec_box* ptr = bump_dp<rust_vec_box*>(dp);
uint8_t* data = &ptr->body.data[0];
return std::make_pair(data, data + ptr->body.fill);
}
template<typename T,typename U>
std::pair<ptr_pair,ptr_pair>
data<T,U>::get_vec_data_range(ptr_pair &dp) {
std::pair<uint8_t *,uint8_t *> fst =
get_vec_data_range(shape::ptr(dp.fst));
std::pair<uint8_t *,uint8_t *> snd =
get_vec_data_range(shape::ptr(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>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_unboxed_vec_data_range(ptr dp) {
rust_vec* ptr = (rust_vec*)dp;
uint8_t* data = &ptr->data[0];
return std::make_pair(data, data + ptr->fill);
}
template<typename T,typename U>
std::pair<ptr_pair,ptr_pair>
data<T,U>::get_unboxed_vec_data_range(ptr_pair &dp) {
std::pair<uint8_t *,uint8_t *> fst =
get_unboxed_vec_data_range(shape::ptr(dp.fst));
std::pair<uint8_t *,uint8_t *> snd =
get_unboxed_vec_data_range(shape::ptr(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>
ptr data<T,U>::get_unboxed_vec_end(ptr dp) {
rust_vec* ptr = (rust_vec*)dp;
return dp + sizeof(rust_vec) + ptr->fill;
}
template<typename T,typename U>
ptr_pair data<T,U>::get_unboxed_vec_end(ptr_pair &dp) {
return ptr_pair(get_unboxed_vec_end(ptr(dp.fst)),
get_unboxed_vec_end(ptr(dp.snd)));
}
template<typename T,typename U>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_slice_data_range(bool is_str, ptr dp) {
uint8_t* ptr = bump_dp<uint8_t*>(dp);
size_t len = bump_dp<size_t>(dp);
if (is_str) len--;
return std::make_pair(ptr, ptr + len);
}
template<typename T,typename U>
std::pair<ptr_pair,ptr_pair>
data<T,U>::get_slice_data_range(bool is_str, ptr_pair &dp) {
std::pair<uint8_t *,uint8_t *> fst =
get_slice_data_range(is_str, shape::ptr(dp.fst));
std::pair<uint8_t *,uint8_t *> snd =
get_slice_data_range(is_str, shape::ptr(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>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_fixedvec_data_range(uint16_t n_elts, size_t elt_sz, ptr dp) {
uint8_t* ptr = (uint8_t*)(dp);
return std::make_pair(ptr, ptr + (((size_t)n_elts) * elt_sz));
}
template<typename T,typename U>
std::pair<ptr_pair,ptr_pair>
data<T,U>::get_fixedvec_data_range(uint16_t n_elts, size_t elt_sz,
ptr_pair &dp) {
std::pair<uint8_t *,uint8_t *> fst =
get_fixedvec_data_range(n_elts, elt_sz, shape::ptr(dp.fst));
std::pair<uint8_t *,uint8_t *> snd =
get_fixedvec_data_range(n_elts, elt_sz, shape::ptr(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_tag1(tag_info &tinfo) {
size_of::compute_tag_size(*this, tinfo);
if (tinfo.variant_count > 1)
ALIGN_TO(rust_alignof<tag_align_t>());
U end_dp = dp + tinfo.tag_sa.size;
typename U::template data<tag_variant_t>::t tag_variant;
if (tinfo.variant_count > 1)
tag_variant = bump_dp<tag_variant_t>(dp);
else
tag_variant = 0;
static_cast<T *>(this)->walk_tag2(tinfo, tag_variant);
dp = end_dp;
}
template<typename T,typename U>
void
data<T,U>::walk_fn_contents1() {
fn_env_pair pair = bump_dp<fn_env_pair>(dp);
if (!pair.env)
return;
arena arena;
const type_desc *closure_td = pair.env->td;
ptr closure_dp((uintptr_t)box_body(pair.env));
T sub(*static_cast<T *>(this), closure_td->shape,
closure_td->shape_tables, closure_dp);
sub.align = true;
sub.walk();
}
template<typename T,typename U>
void
data<T,U>::walk_trait_contents1() {
walk_box_contents1();
}
// Polymorphic logging, for convenience
class log : public data<log,ptr> {
friend class data<log,ptr>;
private:
std::ostream &out;
const char *prefix;
bool in_string;
log(log &other,
const uint8_t *in_sp,
const rust_shape_tables *in_tables = NULL)
: data<log,ptr>(other.task,
other.align,
in_sp,
in_tables ? in_tables : other.tables,
other.dp),
out(other.out),
prefix("") {}
log(log &other,
const uint8_t *in_sp,
const rust_shape_tables *in_tables,
ptr in_dp)
: data<log,ptr>(other.task,
other.align,
in_sp,
in_tables,
in_dp),
out(other.out),
prefix("") {}
log(log &other, ptr in_dp)
: data<log,ptr>(other.task,
other.align,
other.sp,
other.tables,
in_dp),
out(other.out),
prefix("") {}
void walk_vec2(bool is_pod) {
if (!get_dp<void *>(dp))
out << prefix << "(null)";
else
walk_vec2(is_pod, get_vec_data_range(dp));
}
void walk_unboxed_vec2(bool is_pod) {
walk_vec2(is_pod, get_unboxed_vec_data_range(dp));
}
void walk_slice2(bool is_pod, bool is_str) {
walk_vec2(is_pod, get_slice_data_range(is_str, dp));
out << "/&";
}
void walk_fixedvec2(uint16_t n_elts, size_t elt_sz, bool is_pod) {
walk_vec2(is_pod, get_fixedvec_data_range(n_elts, elt_sz, dp));
out << "/" << n_elts;
}
void walk_tag2(tag_info &tinfo, tag_variant_t tag_variant) {
// out << prefix << "tag" << tag_variant;
out << prefix << get_variant_name(tinfo, tag_variant);
data<log,ptr>::walk_variant1(tinfo, tag_variant);
}
void walk_box2() {
out << prefix << "@";
prefix = "";
data<log,ptr>::walk_box_contents1();
}
void walk_uniq2() {
out << prefix << "~";
prefix = "";
data<log,ptr>::walk_uniq_contents1();
}
void walk_rptr2() {
out << prefix << "&";
prefix = "";
data<log,ptr>::walk_rptr_contents1();
}
void walk_fn2(char kind) {
out << prefix << "fn";
prefix = "";
data<log,ptr>::walk_fn_contents1();
}
void walk_trait2() {
out << prefix << "trait(";
prefix = "";
data<log,ptr>::walk_trait_contents1();
out << prefix << ")";
}
void walk_tydesc2(char kind) {
out << prefix << "tydesc";
}
void walk_subcontext2(log &sub) { sub.walk(); }
void walk_box_contents2(log &sub) {
out << prefix;
rust_opaque_box *box_ptr = *(rust_opaque_box **) dp;
if (!box_ptr) {
out << "(null)";
} else {
sub.align = true;
sub.walk();
}
}
void walk_uniq_contents2(log &sub) {
out << prefix;
sub.align = true;
sub.walk();
}
void walk_rptr_contents2(log &sub) {
out << prefix;
sub.align = true;
sub.walk();
}
void walk_struct2(const uint8_t *end_sp);
void walk_vec2(bool is_pod, const std::pair<ptr,ptr> &data);
void walk_slice2(bool is_pod, const std::pair<ptr,ptr> &data);
void walk_variant2(tag_info &tinfo,
tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
void walk_string2(const std::pair<ptr,ptr> &data);
void walk_res2(const rust_fn *dtor, const uint8_t *end_sp);
template<typename T>
inline void walk_number2() {
out << prefix;
fmt_number(out, get_dp<T>(dp));
}
public:
log(rust_task *in_task,
bool in_align,
const uint8_t *in_sp,
const rust_shape_tables *in_tables,
uint8_t *in_data,
std::ostream &in_out)
: data<log,ptr>(in_task, in_align, in_sp, in_tables,
ptr(in_data)),
out(in_out),
prefix("") {}
};
} // end namespace shape
#endif
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
+2 -7
View File
@@ -17,11 +17,6 @@ struct type_desc;
typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *);
struct rust_shape_tables {
uint8_t *tags;
uint8_t *resources;
};
// Corresponds to the boxed data in the @ region. The body follows the
// header; you can obtain a ptr via box_body() below.
struct rust_opaque_box {
@@ -52,8 +47,8 @@ struct type_desc {
glue_fn *drop_glue;
glue_fn *free_glue;
glue_fn *visit_glue;
const uint8_t *shape;
const rust_shape_tables *shape_tables;
const uint8_t *unused;
const uint8_t *unused2;
};
extern "C" type_desc *rust_clone_type_desc(type_desc*);
+4 -50
View File
@@ -301,12 +301,8 @@ rust_upcall_free(void* ptr) {
extern "C" CDECL void
upcall_validate_box(rust_opaque_box* ptr) {
if (ptr) {
assert(ptr->ref_count > 0);
assert(ptr->td != NULL);
assert(ptr->td->align <= 8);
assert(ptr->td->size <= 4096); // might not really be true...
}
// XXX: Remove after snapshot
abort();
}
/**********************************************************************/
@@ -365,52 +361,10 @@ upcall_rust_personality(int version,
return args.retval;
}
extern "C" void
shape_cmp_type(int8_t *result, const type_desc *tydesc,
uint8_t *data_0, uint8_t *data_1, uint8_t cmp_type);
struct s_cmp_type_args {
int8_t *result;
const type_desc *tydesc;
uint8_t *data_0;
uint8_t *data_1;
uint8_t cmp_type;
};
extern "C" void
upcall_s_cmp_type(s_cmp_type_args *args) {
shape_cmp_type(args->result, args->tydesc,
args->data_0, args->data_1, args->cmp_type);
}
extern "C" void
upcall_cmp_type(int8_t *result, const type_desc *tydesc,
uint8_t *data_0, uint8_t *data_1, uint8_t cmp_type) {
rust_task *task = rust_get_current_task();
s_cmp_type_args args = {result, tydesc,
data_0, data_1, cmp_type};
UPCALL_SWITCH_STACK(task, &args, upcall_s_cmp_type);
}
extern "C" void
shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level);
struct s_log_type_args {
const type_desc *tydesc;
uint8_t *data;
uint32_t level;
};
extern "C" void
upcall_s_log_type(s_log_type_args *args) {
shape_log_type(args->tydesc, args->data, args->level);
}
extern "C" void
upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
rust_task *task = rust_get_current_task();
s_log_type_args args = {tydesc, data, level};
UPCALL_SWITCH_STACK(task, &args, upcall_s_log_type);
// XXX: Remove after snapshot
abort();
}
// NB: This needs to be blazing fast. Don't switch stacks
+2 -12
View File
@@ -1,19 +1,9 @@
#include "rust_type.h"
#include "rust_shape.h"
// A hardcoded type descriptor for strings, since the runtime needs to
// be able to create them.
struct rust_shape_tables empty_shape_tables;
uint8_t str_body_shape[] = {
shape::SHAPE_UNBOXED_VEC,
0x1, // is_pod
0x1, 0x0, // size field: 1
shape::SHAPE_U8
};
struct type_desc str_body_tydesc = {
1, // size
1, // align
@@ -21,8 +11,8 @@ struct type_desc str_body_tydesc = {
NULL, // drop_glue
NULL, // free_glue
NULL, // visit_glue
str_body_shape, // shape
&empty_shape_tables, // shape_tables
NULL, // shape
NULL, // shape_tables
};
//
-2
View File
@@ -64,14 +64,12 @@ rust_get_stack_segment
rust_task_weaken
rust_task_unweaken
rust_log_str
shape_log_str
start_task
vec_reserve_shared_actual
vec_reserve_shared
task_clear_event_reject
task_wait_event
task_signal_event
upcall_cmp_type
upcall_fail
upcall_trace
upcall_free