rustc: Use polymorphic logging

This commit is contained in:
Patrick Walton 2011-08-10 12:55:29 -07:00
parent 40ae704ff2
commit adce35acd4
5 changed files with 116 additions and 129 deletions

View file

@ -26,11 +26,6 @@ import lib::llvm::llvm::TypeRef;
type upcalls =
{grow_task: ValueRef,
log_int: ValueRef,
log_float: ValueRef,
log_double: ValueRef,
log_str: ValueRef,
log_istr: ValueRef,
trace_word: ValueRef,
trace_str: ValueRef,
new_port: ValueRef,
@ -67,7 +62,8 @@ type upcalls =
ivec_spill: ValueRef,
ivec_resize_shared: ValueRef,
ivec_spill_shared: ValueRef,
cmp_type: ValueRef};
cmp_type: ValueRef,
log_type: ValueRef};
fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
taskptr_type: TypeRef, llmod: ModuleRef) -> @upcalls {
@ -89,11 +85,6 @@ fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
let empty_vec: [TypeRef] = ~[];
ret @{grow_task: dv("grow_task", ~[T_size_t()]),
log_int: dv("log_int", ~[T_i32(), T_i32()]),
log_float: dv("log_float", ~[T_i32(), T_f32()]),
log_double: dv("log_double", ~[T_i32(), T_ptr(T_f64())]),
log_str: dv("log_str", ~[T_i32(), T_ptr(T_str())]),
log_istr: dv("log_istr", ~[T_i32(), T_ptr(T_ivec(T_i8()))]),
trace_word: dv("trace_word", ~[T_int()]),
trace_str: dv("trace_str", ~[T_ptr(T_i8())]),
new_port: d("new_port", ~[T_size_t()], T_opaque_port_ptr()),
@ -159,6 +150,10 @@ fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
dr("cmp_type", ~[T_ptr(T_i1()), taskptr_type,
T_ptr(tydesc_type), T_ptr(T_ptr(tydesc_type)),
T_ptr(T_i8()), T_ptr(T_i8()), T_i8()],
T_void()),
log_type:
dr("log_type", ~[taskptr_type, T_ptr(tydesc_type),
T_ptr(T_i8()), T_i32()],
T_void())};
}
//

View file

@ -5190,48 +5190,18 @@ fn trans_log(lvl: int, cx: &@block_ctxt, e: &@ast::expr) -> result {
let sub = trans_expr(log_cx, e);
let e_ty = ty::expr_ty(bcx_tcx(cx), e);
let log_bcx = sub.bcx;
if ty::type_is_fp(bcx_tcx(cx), e_ty) {
let tr: TypeRef;
let is32bit: bool = false;
alt ty::struct(bcx_tcx(cx), e_ty) {
ty::ty_machine(ast::ty_f32.) { tr = T_f32(); is32bit = true; }
ty::ty_machine(ast::ty_f64.) { tr = T_f64(); }
_ { tr = T_float(); }
}
if is32bit {
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_float,
~[log_bcx.fcx.lltaskptr, C_int(lvl), sub.val]);
} else {
// FIXME: Eliminate this level of indirection.
let tmp = alloca(log_bcx, tr);
sub.bcx.build.Store(sub.val, tmp);
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_double,
~[log_bcx.fcx.lltaskptr, C_int(lvl), tmp]);
}
} else if (ty::type_is_integral(bcx_tcx(cx), e_ty) ||
ty::type_is_bool(bcx_tcx(cx), e_ty)) {
// FIXME: Handle signedness properly.
let ti = none[@tydesc_info];
let r = get_tydesc(log_bcx, e_ty, false, ti);
log_bcx = r.bcx;
let llintval =
int_cast(log_bcx, T_int(), val_ty(sub.val), sub.val, false);
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_int,
~[log_bcx.fcx.lltaskptr, C_int(lvl), llintval]);
} else {
alt ty::struct(bcx_tcx(cx), e_ty) {
ty::ty_str. {
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_str,
~[log_bcx.fcx.lltaskptr, C_int(lvl), sub.val]);
}
_ {
// FIXME: Support these types.
// Call the polymorphic log function.
let llvalptr = spill_if_immediate(log_bcx, sub.val, e_ty);
let llval_i8 = log_bcx.build.PointerCast(llvalptr, T_ptr(T_i8()));
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_type,
~[log_bcx.fcx.lltaskptr, r.val, llval_i8, C_int(lvl)]);
bcx_ccx(cx).sess.span_fatal(e.span,
"log called on unsupported type " +
ty_to_str(bcx_tcx(cx), e_ty));
}
}
}
log_bcx = trans_block_cleanups(log_bcx, log_cx);
log_bcx.build.Br(after_cx.llbb);
ret rslt(after_cx, C_nil());

View file

@ -343,36 +343,6 @@ fn trans_log(cx: &@block_ctxt, sp: &span, level: int, expr: &@ast::expr) ->
ret lllevelptr;
}
tag upcall_style { us_imm; us_imm_i32_zext; us_alias; us_alias_istr; }
fn get_upcall(ccx: &@crate_ctxt, sp: &span, t: ty::t) ->
{val: ValueRef, st: upcall_style} {
alt ty::struct(ccx_tcx(ccx), t) {
ty::ty_machine(ast::ty_f32.) {
ret {val: ccx.upcalls.log_float, st: us_imm};
}
ty::ty_machine(ast::ty_f64.) | ty::ty_float. {
// TODO: We have to spill due to legacy calling conventions that
// should probably be modernized.
ret {val: ccx.upcalls.log_double, st: us_alias};
}
ty::ty_bool. | ty::ty_machine(ast::ty_i8.) |
ty::ty_machine(ast::ty_i16.) | ty::ty_machine(ast::ty_u8.) |
ty::ty_machine(ast::ty_u16.) {
ret {val: ccx.upcalls.log_int, st: us_imm_i32_zext};
}
ty::ty_int. | ty::ty_machine(ast::ty_i32.) |
ty::ty_machine(ast::ty_u32.) {
ret {val: ccx.upcalls.log_int, st: us_imm};
}
ty::ty_istr. { ret {val: ccx.upcalls.log_istr, st: us_alias_istr}; }
_ {
ccx.sess.span_unimpl(sp,
"logging for values of type " +
ppaux::ty_to_str(ccx_tcx(ccx), t));
}
}
}
let bcx = cx;
let lllevelptr = trans_log_level(bcx_lcx(bcx));
@ -386,34 +356,20 @@ fn trans_log(cx: &@block_ctxt, sp: &span, level: int, expr: &@ast::expr) ->
bcx.build.CondBr(should_log, log_bcx.llbb, next_bcx.llbb);
let expr_t = ty::expr_ty(bcx_tcx(log_bcx), expr);
let r = get_upcall(bcx_ccx(bcx), sp, expr_t);
let llupcall = r.val;
let style = r.st;
let arg_dest;
alt style {
us_imm. | us_imm_i32_zext. {
arg_dest = dest_imm(bcx_tcx(log_bcx), expr_t);
}
us_alias. | us_alias_istr. {
arg_dest = dest_alias(bcx_tcx(log_bcx), expr_t);
}
}
let arg_dest = dest_alias(bcx_tcx(log_bcx), expr_t);
log_bcx = trans_expr(log_bcx, arg_dest, expr);
let llarg = dest_llval(arg_dest);
alt style {
us_imm. | us_alias. {/* no-op */ }
us_imm_i32_zext. { llarg = log_bcx.build.ZExt(llarg, tc::T_i32()); }
us_alias_istr. {
llarg =
log_bcx.build.PointerCast(llarg,
tc::T_ptr(tc::T_ivec(tc::T_i8())));
}
}
let llarg_i8 = bcx.build.PointerCast(llarg, T_ptr(T_i8()));
log_bcx.build.Call(llupcall,
~[bcx_fcx(bcx).lltaskptr, tc::C_int(level), llarg]);
let ti = none;
let r2 = trans::get_tydesc(bcx, expr_t, false, ti);
bcx = r2.bcx;
let lltydesc = r2.val;
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_type,
~[bcx_fcx(bcx).lltaskptr, lltydesc, llarg_i8,
tc::C_int(level)]);
log_bcx =
trans::trans_block_cleanups(log_bcx, tc::find_scope_cx(log_bcx));

View file

@ -3,6 +3,7 @@
#include <algorithm>
#include <iostream>
#include <sstream>
#include <utility>
#include <cassert>
#include <cstdio>
@ -76,20 +77,6 @@ align_to(T size, size_t alignment) {
return x;
}
template<typename T>
static inline T
bump_dp(uint8_t *&dp) {
T x = *((T *)dp);
dp += sizeof(T);
return x;
}
template<typename T>
static inline T
get_dp(uint8_t *dp) {
return *((T *)dp);
}
// Utility classes
struct size_align {
@ -220,6 +207,52 @@ get_dp(ptr_pair &ptr) {
return data;
}
// Pointer wrappers for data traversals
class ptr {
private:
uint8_t *p;
public:
template<typename T>
struct data { typedef T t; };
ptr(uint8_t *in_p)
: p(in_p) {}
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; }
template<typename T>
inline operator T *() { return (T *)p; }
inline operator uintptr_t() { return (uintptr_t)p; }
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);
}
// Contexts
@ -852,8 +885,8 @@ 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_evec_data_range(uint8_t *dp);
static std::pair<uint8_t *,uint8_t *> get_ivec_data_range(uint8_t *dp);
static std::pair<uint8_t *,uint8_t *> get_evec_data_range(ptr dp);
static std::pair<uint8_t *,uint8_t *> get_ivec_data_range(ptr dp);
static std::pair<ptr_pair,ptr_pair> get_evec_data_range(ptr_pair &dp);
static std::pair<ptr_pair,ptr_pair> get_ivec_data_range(ptr_pair &dp);
@ -924,14 +957,14 @@ data<T,U>::walk_variant(bool align, tag_info &tinfo, uint32_t variant_id) {
template<typename T,typename U>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_evec_data_range(uint8_t *dp) {
data<T,U>::get_evec_data_range(ptr dp) {
rust_vec *vp = bump_dp<rust_vec *>(dp);
return std::make_pair(vp->data, vp->data + vp->fill);
}
template<typename T,typename U>
std::pair<uint8_t *,uint8_t *>
data<T,U>::get_ivec_data_range(uint8_t *dp) {
data<T,U>::get_ivec_data_range(ptr dp) {
size_t fill = bump_dp<size_t>(dp);
bump_dp<size_t>(dp); // Skip over alloc.
uint8_t *payload_dp = dp;
@ -1009,6 +1042,8 @@ data<T,U>::walk_tag(bool align, tag_info &tinfo) {
tag_variant = 0;
static_cast<T *>(this)->walk_tag(align, tinfo, tag_variant);
dp = end_dp;
}
@ -1187,13 +1222,20 @@ cmp::walk_variant(bool align, tag_info &tinfo, uint32_t variant_id,
// Polymorphic logging, for convenience
class log : public data<log,uint8_t *> {
friend class data<log,uint8_t *>;
class log : public data<log,ptr> {
friend class data<log,ptr>;
private:
std::ostream &out;
bool in_string;
log(log &other,
const uint8_t *in_sp,
const type_param *in_params,
const rust_shape_tables *in_tables)
: data<log,ptr>(other.task, in_sp, in_params, in_tables, other.dp),
out(other.out) {}
void walk_evec(bool align, bool is_pod, uint16_t sp_size) {
walk_vec(align, is_pod, get_evec_data_range(dp));
}
@ -1202,8 +1244,14 @@ private:
walk_vec(align, is_pod, get_ivec_data_range(dp));
}
void walk_vec(bool align, bool is_pod,
const std::pair<uint8_t *,uint8_t *> &data);
void walk_tag(bool align, tag_info &tinfo, uint32_t tag_variant) {
out << "tag" << tag_variant;
// TODO: Print insides.
}
void walk_subcontext(bool align, log &sub) { sub.walk(align); }
void walk_vec(bool align, bool is_pod, const std::pair<ptr,ptr> &data);
template<typename T>
void walk_number() { out << get_dp<T>(dp); }
@ -1215,13 +1263,12 @@ public:
const rust_shape_tables *in_tables,
uint8_t *in_data,
std::ostream &in_out)
: data<log,uint8_t *>(in_task, in_sp, in_params, in_tables, in_data),
: data<log,ptr>(in_task, in_sp, in_params, in_tables, in_data),
out(in_out) {}
};
void
log::walk_vec(bool align, bool is_pod,
const std::pair<uint8_t *,uint8_t *> &data) {
log::walk_vec(bool align, bool is_pod, const std::pair<ptr,ptr> &data) {
// TODO: Check to see whether this is a string (contains u8). If so,
// write the vector ""-style; otherwise [ ... , ... ] style.
}
@ -1245,3 +1292,21 @@ upcall_cmp_type(int8_t *result, rust_task *task, type_desc *tydesc,
}
}
extern "C" void
upcall_log_type(rust_task *task, type_desc *tydesc, uint8_t *data,
uint32_t level) {
if (task->sched->log_lvl < level)
return; // TODO: Don't evaluate at all?
shape::arena arena;
shape::type_param *params = shape::type_param::make(tydesc, arena);
std::stringstream ss;
shape::log log(task, tydesc->shape, params, tydesc->shape_tables, data,
ss);
log.walk(true);
task->sched->log(task, level, "%s", ss.str().c_str());
}

View file

@ -97,6 +97,7 @@ upcall_log_float
upcall_log_int
upcall_log_istr
upcall_log_str
upcall_log_type
upcall_malloc
upcall_mark
upcall_new_chan