rustc: Use polymorphic logging
This commit is contained in:
parent
40ae704ff2
commit
adce35acd4
5 changed files with 116 additions and 129 deletions
|
@ -26,11 +26,6 @@ import lib::llvm::llvm::TypeRef;
|
||||||
|
|
||||||
type upcalls =
|
type upcalls =
|
||||||
{grow_task: ValueRef,
|
{grow_task: ValueRef,
|
||||||
log_int: ValueRef,
|
|
||||||
log_float: ValueRef,
|
|
||||||
log_double: ValueRef,
|
|
||||||
log_str: ValueRef,
|
|
||||||
log_istr: ValueRef,
|
|
||||||
trace_word: ValueRef,
|
trace_word: ValueRef,
|
||||||
trace_str: ValueRef,
|
trace_str: ValueRef,
|
||||||
new_port: ValueRef,
|
new_port: ValueRef,
|
||||||
|
@ -67,7 +62,8 @@ type upcalls =
|
||||||
ivec_spill: ValueRef,
|
ivec_spill: ValueRef,
|
||||||
ivec_resize_shared: ValueRef,
|
ivec_resize_shared: ValueRef,
|
||||||
ivec_spill_shared: ValueRef,
|
ivec_spill_shared: ValueRef,
|
||||||
cmp_type: ValueRef};
|
cmp_type: ValueRef,
|
||||||
|
log_type: ValueRef};
|
||||||
|
|
||||||
fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
|
fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
|
||||||
taskptr_type: TypeRef, llmod: ModuleRef) -> @upcalls {
|
taskptr_type: TypeRef, llmod: ModuleRef) -> @upcalls {
|
||||||
|
@ -89,11 +85,6 @@ fn declare_upcalls(tn: type_names, tydesc_type: TypeRef,
|
||||||
|
|
||||||
let empty_vec: [TypeRef] = ~[];
|
let empty_vec: [TypeRef] = ~[];
|
||||||
ret @{grow_task: dv("grow_task", ~[T_size_t()]),
|
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_word: dv("trace_word", ~[T_int()]),
|
||||||
trace_str: dv("trace_str", ~[T_ptr(T_i8())]),
|
trace_str: dv("trace_str", ~[T_ptr(T_i8())]),
|
||||||
new_port: d("new_port", ~[T_size_t()], T_opaque_port_ptr()),
|
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,
|
dr("cmp_type", ~[T_ptr(T_i1()), taskptr_type,
|
||||||
T_ptr(tydesc_type), T_ptr(T_ptr(tydesc_type)),
|
T_ptr(tydesc_type), T_ptr(T_ptr(tydesc_type)),
|
||||||
T_ptr(T_i8()), T_ptr(T_i8()), T_i8()],
|
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())};
|
T_void())};
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
|
@ -5190,48 +5190,18 @@ fn trans_log(lvl: int, cx: &@block_ctxt, e: &@ast::expr) -> result {
|
||||||
let sub = trans_expr(log_cx, e);
|
let sub = trans_expr(log_cx, e);
|
||||||
let e_ty = ty::expr_ty(bcx_tcx(cx), e);
|
let e_ty = ty::expr_ty(bcx_tcx(cx), e);
|
||||||
let log_bcx = sub.bcx;
|
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);
|
let ti = none[@tydesc_info];
|
||||||
sub.bcx.build.Store(sub.val, tmp);
|
let r = get_tydesc(log_bcx, e_ty, false, ti);
|
||||||
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_double,
|
log_bcx = r.bcx;
|
||||||
~[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 llintval =
|
// Call the polymorphic log function.
|
||||||
int_cast(log_bcx, T_int(), val_ty(sub.val), sub.val, false);
|
let llvalptr = spill_if_immediate(log_bcx, sub.val, e_ty);
|
||||||
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_int,
|
let llval_i8 = log_bcx.build.PointerCast(llvalptr, T_ptr(T_i8()));
|
||||||
~[log_bcx.fcx.lltaskptr, C_int(lvl), llintval]);
|
|
||||||
} else {
|
log_bcx.build.Call(bcx_ccx(log_bcx).upcalls.log_type,
|
||||||
alt ty::struct(bcx_tcx(cx), e_ty) {
|
~[log_bcx.fcx.lltaskptr, r.val, llval_i8, C_int(lvl)]);
|
||||||
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.
|
|
||||||
|
|
||||||
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 = trans_block_cleanups(log_bcx, log_cx);
|
||||||
log_bcx.build.Br(after_cx.llbb);
|
log_bcx.build.Br(after_cx.llbb);
|
||||||
ret rslt(after_cx, C_nil());
|
ret rslt(after_cx, C_nil());
|
||||||
|
|
|
@ -343,36 +343,6 @@ fn trans_log(cx: &@block_ctxt, sp: &span, level: int, expr: &@ast::expr) ->
|
||||||
ret lllevelptr;
|
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 bcx = cx;
|
||||||
|
|
||||||
let lllevelptr = trans_log_level(bcx_lcx(bcx));
|
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);
|
bcx.build.CondBr(should_log, log_bcx.llbb, next_bcx.llbb);
|
||||||
|
|
||||||
let expr_t = ty::expr_ty(bcx_tcx(log_bcx), expr);
|
let expr_t = ty::expr_ty(bcx_tcx(log_bcx), expr);
|
||||||
let r = get_upcall(bcx_ccx(bcx), sp, expr_t);
|
let arg_dest = dest_alias(bcx_tcx(log_bcx), 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log_bcx = trans_expr(log_bcx, arg_dest, expr);
|
log_bcx = trans_expr(log_bcx, arg_dest, expr);
|
||||||
|
|
||||||
let llarg = dest_llval(arg_dest);
|
let llarg = dest_llval(arg_dest);
|
||||||
alt style {
|
let llarg_i8 = bcx.build.PointerCast(llarg, T_ptr(T_i8()));
|
||||||
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())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log_bcx.build.Call(llupcall,
|
let ti = none;
|
||||||
~[bcx_fcx(bcx).lltaskptr, tc::C_int(level), llarg]);
|
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 =
|
log_bcx =
|
||||||
trans::trans_block_cleanups(log_bcx, tc::find_scope_cx(log_bcx));
|
trans::trans_block_cleanups(log_bcx, tc::find_scope_cx(log_bcx));
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -76,20 +77,6 @@ align_to(T size, size_t alignment) {
|
||||||
return x;
|
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
|
// Utility classes
|
||||||
|
|
||||||
struct size_align {
|
struct size_align {
|
||||||
|
@ -220,6 +207,52 @@ get_dp(ptr_pair &ptr) {
|
||||||
return data;
|
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
|
// Contexts
|
||||||
|
|
||||||
|
@ -852,8 +885,8 @@ class data : public ctxt< data<T,U> > {
|
||||||
protected:
|
protected:
|
||||||
void walk_variant(bool align, tag_info &tinfo, uint32_t variant);
|
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_evec_data_range(ptr dp);
|
||||||
static std::pair<uint8_t *,uint8_t *> get_ivec_data_range(uint8_t *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_evec_data_range(ptr_pair &dp);
|
||||||
static std::pair<ptr_pair,ptr_pair> get_ivec_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>
|
template<typename T,typename U>
|
||||||
std::pair<uint8_t *,uint8_t *>
|
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);
|
rust_vec *vp = bump_dp<rust_vec *>(dp);
|
||||||
return std::make_pair(vp->data, vp->data + vp->fill);
|
return std::make_pair(vp->data, vp->data + vp->fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T,typename U>
|
template<typename T,typename U>
|
||||||
std::pair<uint8_t *,uint8_t *>
|
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);
|
size_t fill = bump_dp<size_t>(dp);
|
||||||
bump_dp<size_t>(dp); // Skip over alloc.
|
bump_dp<size_t>(dp); // Skip over alloc.
|
||||||
uint8_t *payload_dp = dp;
|
uint8_t *payload_dp = dp;
|
||||||
|
@ -1009,6 +1042,8 @@ data<T,U>::walk_tag(bool align, tag_info &tinfo) {
|
||||||
tag_variant = 0;
|
tag_variant = 0;
|
||||||
|
|
||||||
static_cast<T *>(this)->walk_tag(align, tinfo, tag_variant);
|
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
|
// Polymorphic logging, for convenience
|
||||||
|
|
||||||
class log : public data<log,uint8_t *> {
|
class log : public data<log,ptr> {
|
||||||
friend class data<log,uint8_t *>;
|
friend class data<log,ptr>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream &out;
|
std::ostream &out;
|
||||||
bool in_string;
|
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) {
|
void walk_evec(bool align, bool is_pod, uint16_t sp_size) {
|
||||||
walk_vec(align, is_pod, get_evec_data_range(dp));
|
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));
|
walk_vec(align, is_pod, get_ivec_data_range(dp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void walk_vec(bool align, bool is_pod,
|
void walk_tag(bool align, tag_info &tinfo, uint32_t tag_variant) {
|
||||||
const std::pair<uint8_t *,uint8_t *> &data);
|
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>
|
template<typename T>
|
||||||
void walk_number() { out << get_dp<T>(dp); }
|
void walk_number() { out << get_dp<T>(dp); }
|
||||||
|
@ -1215,13 +1263,12 @@ public:
|
||||||
const rust_shape_tables *in_tables,
|
const rust_shape_tables *in_tables,
|
||||||
uint8_t *in_data,
|
uint8_t *in_data,
|
||||||
std::ostream &in_out)
|
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) {}
|
out(in_out) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
log::walk_vec(bool align, bool is_pod,
|
log::walk_vec(bool align, bool is_pod, const std::pair<ptr,ptr> &data) {
|
||||||
const std::pair<uint8_t *,uint8_t *> &data) {
|
|
||||||
// TODO: Check to see whether this is a string (contains u8). If so,
|
// TODO: Check to see whether this is a string (contains u8). If so,
|
||||||
// write the vector ""-style; otherwise [ ... , ... ] style.
|
// 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ upcall_log_float
|
||||||
upcall_log_int
|
upcall_log_int
|
||||||
upcall_log_istr
|
upcall_log_istr
|
||||||
upcall_log_str
|
upcall_log_str
|
||||||
|
upcall_log_type
|
||||||
upcall_malloc
|
upcall_malloc
|
||||||
upcall_mark
|
upcall_mark
|
||||||
upcall_new_chan
|
upcall_new_chan
|
||||||
|
|
Loading…
Reference in a new issue