diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index cf88515cd4c..220fec81e8e 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -39,6 +39,8 @@ 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; diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index c7ad35b52fd..b8327ad234a 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -66,7 +66,8 @@ fn next(str prefix) -> str { 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". @@ -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; } @@ -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 @@ -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); @@ -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; @@ -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); @@ -1621,26 +1649,35 @@ 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); @@ -1648,8 +1685,11 @@ fn declare_generic_glue(@local_ctxt cx, @ty.t t, str name) -> ValueRef { 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; @@ -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()); } @@ -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);