Rust内在的名为“transmute”的实际实现在哪里?

时间:2014-05-10 15:32:15

标签: rust

我正在尝试找到Rust内在函数的实现,特别是带有一个参数的“transumte”内在函数。

我在cast.rs中看过以下代码,但正如您所看到的,它只是委托其他一些transmute实现。

#[inline]
pub unsafe fn transmute<L, G>(thing: L) -> G {
    intrinsics::transmute(thing)
}

内在函数的实际实现在哪里,尤其是transmute内在函数?

1 个答案:

答案 0 :(得分:3)

cast::transmute代表intrinsics::transmute。有一个名为intrinsics的模块(现在在libcore中),它包含extern绑定到多个函数,包括transmute。从模块文档中可以看出,内部函数的实现据说位于librustc/middle/trans/foreign.rs

但是,据我所知,librustc/middle/trans/intrinsic.rs中存在内在函数的实际实现。你可以搜索transmute,然后你会发现一个非常大的match语句,看起来像这样:

    "transmute" => {
        let (in_type, out_type) = (*substs.substs.tps.get(0),
                                   *substs.substs.tps.get(1));
        let llintype = type_of::type_of(ccx, in_type);
        let llouttype = type_of::type_of(ccx, out_type);

        let in_type_size = machine::llbitsize_of_real(ccx, llintype);
        let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
        if in_type_size != out_type_size {
            let sp = match ccx.tcx.map.get(ref_id.unwrap()) {
                ast_map::NodeExpr(e) => e.span,
                _ => fail!("transmute has non-expr arg"),
            };
            ccx.sess().span_fatal(sp,
                format!("transmute called on types with different sizes: \
                         {intype} ({insize, plural, =1{# bit} other{# bits}}) to \
                         {outtype} ({outsize, plural, =1{# bit} other{# bits}})",
                        intype = ty_to_str(ccx.tcx(), in_type),
                        insize = in_type_size as uint,
                        outtype = ty_to_str(ccx.tcx(), out_type),
                        outsize = out_type_size as uint));
        }

        if !return_type_is_void(ccx, out_type) {
            let llsrcval = get_param(decl, first_real_arg);
            if type_is_immediate(ccx, in_type) {
                match fcx.llretptr.get() {
                    Some(llretptr) => {
                        Store(bcx, llsrcval, PointerCast(bcx, llretptr, llintype.ptr_to()));
                        RetVoid(bcx);
                    }
                    None => match (llintype.kind(), llouttype.kind()) {
                        (Pointer, other) | (other, Pointer) if other != Pointer => {
                            let tmp = Alloca(bcx, llouttype, "");
                            Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
                            Ret(bcx, Load(bcx, tmp));
                        }
                        (Array, _) | (_, Array) | (Struct, _) | (_, Struct) => {
                            let tmp = Alloca(bcx, llouttype, "");
                            Store(bcx, llsrcval, PointerCast(bcx, tmp, llintype.ptr_to()));
                            Ret(bcx, Load(bcx, tmp));
                        }
                        _ => {
                            let llbitcast = BitCast(bcx, llsrcval, llouttype);
                            Ret(bcx, llbitcast)
                        }
                    }
                }
            } else if type_is_immediate(ccx, out_type) {
                let llsrcptr = PointerCast(bcx, llsrcval, llouttype.ptr_to());
                let ll_load = Load(bcx, llsrcptr);
                Ret(bcx, ll_load);
            } else {
                // NB: Do not use a Load and Store here. This causes massive
                // code bloat when `transmute` is used on large structural
                // types.
                let lldestptr = fcx.llretptr.get().unwrap();
                let lldestptr = PointerCast(bcx, lldestptr, Type::i8p(ccx));
                let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p(ccx));

                let llsize = llsize_of(ccx, llintype);
                call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
                RetVoid(bcx);
            };
        } else {
            RetVoid(bcx);
        }
    }

这似乎是生成将插入代码而不是调用transmute的代码的代码。我没有编译专家,所以如果我错了,请有人纠正我。