Skip to content

Commit

Permalink
rustc: Create stub glue for structural comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
pcwalton committed Apr 18, 2011
1 parent ef62fae commit abd78f2
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 23 deletions.
2 changes: 2 additions & 0 deletions src/comp/back/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const int tydesc_field_sever_glue = 6;
const int tydesc_field_mark_glue = 7;
const int tydesc_field_obj_drop_glue = 8;
const int tydesc_field_is_stateful = 9;
const int tydesc_field_cmp_glue = 10;
const int n_tydesc_fields = 11;


const int obj_field_vtbl = 0;
Expand Down
101 changes: 78 additions & 23 deletions src/comp/middle/trans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type glue_fns = rec(ValueRef activate_glue,

type tydesc_info = rec(ValueRef tydesc,
ValueRef take_glue,
ValueRef drop_glue);
ValueRef drop_glue,
ValueRef cmp_glue);

/*
* A note on nomenclature of linking: "upcall", "extern" and "native".
Expand Down Expand Up @@ -325,19 +326,34 @@ fn T_task(type_names tn) -> TypeRef {
ret t;
}

fn T_tydesc_field(type_names tn, int field) -> TypeRef {
// Bit of a kludge: pick the fn typeref out of the tydesc..
let vec[TypeRef] tydesc_elts =
_vec.init_elt[TypeRef](T_nil(), abi.n_tydesc_fields as uint);
llvm.LLVMGetStructElementTypes(T_tydesc(tn),
_vec.buf[TypeRef](tydesc_elts));
auto t = llvm.LLVMGetElementType(tydesc_elts.(field));
ret t;
}

fn T_glue_fn(type_names tn) -> TypeRef {
auto s = "glue_fn";
if (tn.name_has_type(s)) {
ret tn.get_type(s);
}

// Bit of a kludge: pick the fn typeref out of the tydesc..
let vec[TypeRef] tydesc_elts = _vec.init_elt[TypeRef](T_nil(), 10u);
llvm.LLVMGetStructElementTypes(T_tydesc(tn),
_vec.buf[TypeRef](tydesc_elts));
auto t =
llvm.LLVMGetElementType
(tydesc_elts.(abi.tydesc_field_drop_glue));
auto t = T_tydesc_field(tn, abi.tydesc_field_drop_glue);
tn.associate(s, t);
ret t;
}

fn T_cmp_glue_fn(type_names tn) -> TypeRef {
auto s = "cmp_glue_fn";
if (tn.name_has_type(s)) {
ret tn.get_type(s);
}

auto t = T_tydesc_field(tn, abi.tydesc_field_cmp_glue);
tn.associate(s, t);
ret t;
}
Expand All @@ -358,6 +374,12 @@ fn T_tydesc(type_names tn) -> TypeRef {
T_ptr(T_nil()),
tydescpp,
pvoid), T_void()));
auto cmp_glue_fn_ty = T_ptr(T_fn(vec(T_ptr(T_nil()),
T_taskptr(tn),
T_ptr(T_nil()),
tydescpp,
pvoid,
pvoid), T_void()));
auto tydesc = T_struct(vec(tydescpp, // first_param
T_int(), // size
T_int(), // align
Expand All @@ -367,7 +389,8 @@ fn T_tydesc(type_names tn) -> TypeRef {
glue_fn_ty, // sever_glue
glue_fn_ty, // mark_glue
glue_fn_ty, // obj_drop_glue
glue_fn_ty)); // is_stateful
glue_fn_ty, // is_stateful
cmp_glue_fn_ty)); // cmp_glue

llvm.LLVMRefineType(abs_tydesc, tydesc);
auto t = llvm.LLVMResolveTypeHandle(th.llth);
Expand Down Expand Up @@ -1580,8 +1603,12 @@ fn get_tydesc(&@block_ctxt cx, @ty.t t) -> result {
// needs to be separate from make_tydesc() below, because sometimes type glue
// functions needs to refer to their own type descriptors.
fn declare_tydesc(@local_ctxt cx, @ty.t t) {
auto take_glue = declare_generic_glue(cx, t, "take");
auto drop_glue = declare_generic_glue(cx, t, "drop");
auto take_glue = declare_generic_glue(cx, t, T_glue_fn(cx.ccx.tn),
"take");
auto drop_glue = declare_generic_glue(cx, t, T_glue_fn(cx.ccx.tn),
"drop");
auto cmp_glue = declare_generic_glue(cx, t, T_cmp_glue_fn(cx.ccx.tn),
"cmp");
auto ccx = cx.ccx;

auto llsize;
Expand Down Expand Up @@ -1611,7 +1638,8 @@ fn declare_tydesc(@local_ctxt cx, @ty.t t) {
C_null(glue_fn_ty), // sever_glue
C_null(glue_fn_ty), // mark_glue
C_null(glue_fn_ty), // obj_drop_glue
C_null(glue_fn_ty))); // is_stateful
C_null(glue_fn_ty), // is_stateful
cmp_glue)); // cmp_glue

llvm.LLVMSetInitializer(gvar, tydesc);
llvm.LLVMSetGlobalConstant(gvar, True);
Expand All @@ -1621,35 +1649,47 @@ fn declare_tydesc(@local_ctxt cx, @ty.t t) {
auto info = rec(
tydesc=gvar,
take_glue=take_glue,
drop_glue=drop_glue
drop_glue=drop_glue,
cmp_glue=cmp_glue
);

ccx.tydescs.insert(t, @info);
}

tag make_generic_glue_helper_fn {
mgghf_single(val_and_ty_fn);
mgghf_pair(val_pair_and_ty_fn);
}

// declare_tydesc() above must have been called first.
fn define_tydesc(@local_ctxt cx, @ty.t t, vec[uint] ty_params) {
auto info = cx.ccx.tydescs.get(t);
auto gvar = info.tydesc;

auto tg = make_take_glue;
auto take_glue = make_generic_glue(cx, t, info.take_glue, tg, ty_params);
make_generic_glue(cx, t, info.take_glue, mgghf_single(tg), ty_params);
auto dg = make_drop_glue;
auto drop_glue = make_generic_glue(cx, t, info.drop_glue, dg, ty_params);
make_generic_glue(cx, t, info.drop_glue, mgghf_single(dg), ty_params);
auto cg = make_cmp_glue;
make_generic_glue(cx, t, info.cmp_glue, mgghf_pair(cg), ty_params);
}

fn declare_generic_glue(@local_ctxt cx, @ty.t t, str name) -> ValueRef {
auto llfnty = T_glue_fn(cx.ccx.tn);

fn declare_generic_glue(@local_ctxt cx,
@ty.t t,
TypeRef llfnty,
str name) -> ValueRef {
auto gcx = @rec(path=vec("glue", name) with *cx);
auto fn_name = mangle_name_by_type(gcx, t);
fn_name = sanitize(fn_name);
auto llfn = decl_internal_fastcall_fn(cx.ccx.llmod, fn_name, llfnty);
ret llfn;
}

fn make_generic_glue(@local_ctxt cx, @ty.t t, ValueRef llfn,
val_and_ty_fn helper, vec[uint] ty_params) -> ValueRef {
fn make_generic_glue(@local_ctxt cx,
@ty.t t,
ValueRef llfn,
make_generic_glue_helper_fn helper,
vec[uint] ty_params) -> ValueRef {
auto fcx = new_fn_ctxt(cx, llfn);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
Expand Down Expand Up @@ -1684,10 +1724,19 @@ fn make_generic_glue(@local_ctxt cx, @ty.t t, ValueRef llfn,
}
bcx.fcx.lltydescs = _vec.freeze[ValueRef](lltydescs);

auto llrawptr = llvm.LLVMGetParam(llfn, 4u);
auto llval = bcx.build.BitCast(llrawptr, llty);
auto llrawptr0 = llvm.LLVMGetParam(llfn, 4u);
auto llval0 = bcx.build.BitCast(llrawptr0, llty);

re = helper(bcx, llval, t);
alt (helper) {
case (mgghf_single(?single_fn)) {
re = single_fn(bcx, llval0, t);
}
case (mgghf_pair(?pair_fn)) {
auto llrawptr1 = llvm.LLVMGetParam(llfn, 5u);
auto llval1 = bcx.build.BitCast(llrawptr0, llty);
re = pair_fn(bcx, llval0, llval1, t);
}
}
} else {
re = res(bcx, C_nil());
}
Expand Down Expand Up @@ -1933,6 +1982,12 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx,
ret res(next_cx, phi);
}

fn make_cmp_glue(@block_ctxt cx, ValueRef v0, ValueRef v1, @ty.t t)
-> result {
ret res(cx, C_nil()); // TODO
}


// Tag information

type variant_info = rec(vec[@ty.t] args, @ty.t ctor_ty, ast.def_id id);
Expand Down

0 comments on commit abd78f2

Please sign in to comment.