2012-01-02 05:21:44 -06:00
|
|
|
import trans::*;
|
|
|
|
import trans_common::*;
|
2012-01-02 05:58:31 -06:00
|
|
|
import trans_build::*;
|
2012-01-02 05:21:44 -06:00
|
|
|
import option::{some, none};
|
2012-01-02 06:26:51 -06:00
|
|
|
import syntax::{ast, ast_util};
|
|
|
|
import back::link;
|
2012-01-02 05:58:31 -06:00
|
|
|
import lib::llvm;
|
2012-01-02 06:26:51 -06:00
|
|
|
import llvm::llvm::{ValueRef, TypeRef, LLVMGetParam};
|
2012-01-02 05:21:44 -06:00
|
|
|
|
|
|
|
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
|
2012-01-02 05:58:31 -06:00
|
|
|
id: ast::node_id, tps: [ast::ty_param],
|
|
|
|
_ifce: option::t<@ast::ty>) {
|
2012-01-02 05:21:44 -06:00
|
|
|
let sub_cx = extend_path(cx, name);
|
|
|
|
for m in methods {
|
|
|
|
alt cx.ccx.item_ids.find(m.id) {
|
|
|
|
some(llfn) {
|
|
|
|
trans_fn(extend_path(sub_cx, m.ident), m.span, m.decl, m.body,
|
|
|
|
llfn, impl_self(ty::node_id_to_monotype(cx.ccx.tcx, id)),
|
|
|
|
tps + m.tps, m.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-01-02 06:26:51 -06:00
|
|
|
|
|
|
|
fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} {
|
|
|
|
let out_ty = llvm::llvm::LLVMGetReturnType(ft);
|
|
|
|
let n_args = llvm::llvm::LLVMCountParamTypes(ft);
|
|
|
|
let args = vec::init_elt(0 as TypeRef, n_args);
|
|
|
|
unsafe { llvm::llvm::LLVMGetParamTypes(ft, vec::to_ptr(args)); }
|
|
|
|
{inputs: args, output: out_ty}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
|
|
|
|
extra_tps: [ty::param_bounds], m: @ast::method) -> ValueRef {
|
|
|
|
let real_fn = ccx.item_ids.get(m.id);
|
|
|
|
let {inputs: real_args, output: real_ret} =
|
|
|
|
llfn_arg_tys(llvm::llvm::LLVMGetElementType(val_ty(real_fn)));
|
|
|
|
let env_ty = T_ptr(T_struct([T_ptr(T_i8())] +
|
|
|
|
vec::map(extra_tps,
|
|
|
|
{|_p| T_ptr(ccx.tydesc_type)})));
|
|
|
|
// FIXME[impl] filter and pass along dicts for bounds
|
|
|
|
let wrap_args = [env_ty] + vec::slice(real_args, 0u, 2u) +
|
|
|
|
vec::slice(real_args, 2u + vec::len(extra_tps), vec::len(real_args));
|
|
|
|
let llfn_ty = T_fn(wrap_args, real_ret);
|
|
|
|
|
|
|
|
let lcx = @{path: pt + ["wrapper", m.ident], module_path: [],
|
|
|
|
obj_typarams: [], obj_fields: [], ccx: ccx};
|
|
|
|
let name = link::mangle_internal_name_by_path_and_seq(ccx, pt, m.ident);
|
|
|
|
let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfn_ty);
|
|
|
|
let fcx = new_fn_ctxt(lcx, ast_util::dummy_sp(), llfn);
|
|
|
|
let bcx = new_top_block_ctxt(fcx), lltop = bcx.llbb;
|
|
|
|
|
|
|
|
let dict = LLVMGetParam(llfn, 0u);
|
|
|
|
// retptr, self
|
|
|
|
let args = [LLVMGetParam(llfn, 1u), LLVMGetParam(llfn, 2u)], i = 1;
|
|
|
|
// saved tydescs/dicts
|
|
|
|
for extra_tp in extra_tps {
|
|
|
|
args += [load_inbounds(bcx, dict, [0, i])];
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
// the rest of the parameters
|
|
|
|
let i = 3u, params_total = llvm::llvm::LLVMCountParamTypes(llfn_ty);
|
|
|
|
while i < params_total {
|
|
|
|
args += [LLVMGetParam(llfn, i)];
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
Call(bcx, ccx.item_ids.get(m.id), args);
|
|
|
|
finish_fn(fcx, lltop);
|
|
|
|
ret llfn;
|
|
|
|
}
|
|
|
|
|